package com.niiwoo.civet.trade.service.dubbo.invest;

import com.alibaba.dubbo.common.utils.Assert;
import com.alibaba.dubbo.common.utils.CollectionUtils;
import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.config.annotation.Service;
import com.niiwoo.activity.stage.dto.request.notice.NoviceTaskRecordRequestDTO;
import com.niiwoo.activity.stage.enums.activity.NoviceTaskPrizeEnum;
import com.niiwoo.activity.stage.service.prize.ActivityPrizeDubboService;
import com.niiwoo.civet.account.dto.request.InvestPayDubboRequestDTO;
import com.niiwoo.civet.account.dto.request.QueryMoneyTotalRequestDTO;
import com.niiwoo.civet.account.dto.response.*;
import com.niiwoo.civet.account.service.AccountCompanyDubboService;
import com.niiwoo.civet.account.service.AccountDubboService;
import com.niiwoo.civet.account.service.AccountInvestDubboService;
import com.niiwoo.civet.account.service.MoneyTotalDubboService;
import com.niiwoo.civet.base.utils.ProjectInfoUtil;
import com.niiwoo.civet.trade.constant.AmountHandleConstant;
import com.niiwoo.civet.trade.constant.RabbitConstant;
import com.niiwoo.civet.trade.dao.entity.*;
import com.niiwoo.civet.trade.dao.mapper.*;
import com.niiwoo.civet.trade.dto.common.*;
import com.niiwoo.civet.trade.dto.request.*;
import com.niiwoo.civet.trade.dto.request.fanliInvest.FanLiInvestingProjectPageRequestDTO;
import com.niiwoo.civet.trade.dto.request.myloan.InvestingProjectPageRequestDTO;
import com.niiwoo.civet.trade.dto.response.*;
import com.niiwoo.civet.trade.dto.response.fanliInvest.BidListDTO;
import com.niiwoo.civet.trade.dto.response.fanliInvest.InvestingProjectPageResponseDTO;
import com.niiwoo.civet.trade.dto.response.intelligenceInvest.IntelligenceInvestSwitchResponseDTO;
import com.niiwoo.civet.trade.dto.response.intelligenceInvest.NoviceIntelligenceInvestInfoResponseDTO;
import com.niiwoo.civet.trade.dto.response.invest.InvestmentRateInfoResponseDTO;
import com.niiwoo.civet.trade.dto.response.myloan.Bid;
import com.niiwoo.civet.trade.dto.response.myloan.FanLiProjectDetailResponseDTO;
import com.niiwoo.civet.trade.enums.*;
import com.niiwoo.civet.trade.enums.Intelligence.IntelligenceSwitchSourceEnum;
import com.niiwoo.civet.trade.service.invest.InvestDubboService;
import com.niiwoo.civet.trade.service.local.common.InvestCommonServer;
import com.niiwoo.civet.trade.service.local.configure.InvestFlowConfigLocalService;
import com.niiwoo.civet.trade.service.local.configure.TradeConfigLocalService;
import com.niiwoo.civet.trade.service.local.contract.ContractBaseService;
import com.niiwoo.civet.trade.service.local.contract.vo.InvestorContractDTO;
import com.niiwoo.civet.trade.service.local.intelligenceInvest.IntelligenceInvestService;
import com.niiwoo.civet.trade.service.local.intelligenceInvest.NoviceIntelligenceInvestService;
import com.niiwoo.civet.trade.service.local.invest.AutoBatchInvestService;
import com.niiwoo.civet.trade.service.local.invest.InvestService;
import com.niiwoo.civet.trade.service.local.loan.SpeedLoanService;
import com.niiwoo.civet.trade.service.local.project.ProjectLocalService;
import com.niiwoo.civet.trade.utils.ProjectUtil;
import com.niiwoo.civet.user.dto.UserPersonalDubboInfoDTO;
import com.niiwoo.civet.user.dto.request.SimpleOrgInfo;
import com.niiwoo.civet.user.dto.response.UserBasicInfoDTO;
import com.niiwoo.civet.user.dto.response.UserIdentityInfoResponseDTO;
import com.niiwoo.civet.user.service.*;
import com.niiwoo.tripod.base.component.PrivacyMasks;
import com.niiwoo.tripod.base.enums.UserTypeEnum;
import com.niiwoo.tripod.base.plan.RepaymentPlanContext;
import com.niiwoo.tripod.base.plan.support.PeriodUnitEnum;
import com.niiwoo.tripod.base.plan.support.RepaymentPlanDTO;
import com.niiwoo.tripod.base.plan.support.RepaymentTypeEnum;
import com.niiwoo.tripod.lanmao.enums.UserRoleEnum;
import com.niiwoo.tripod.provider.dto.response.PageResponseDTO;
import com.niiwoo.tripod.provider.exception.BizException;
import com.niiwoo.tripod.service.component.SnowflakeIdWorker;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;

import java.math.BigDecimal;
import java.math.MathContext;
import java.util.*;
import java.util.stream.Collectors;

@Service(version = "1.0.0")
@Slf4j
public class InvestDubboServiceImpl implements InvestDubboService {

    private static final Logger logger = LoggerFactory.getLogger(InvestDubboServiceImpl.class);

    @Reference(version = "1.0.0")
    private AccountDubboService accountDubboService;
    @Reference(version = "1.0.0")
    private AccountInvestDubboService accountInvestDubboService;
    @Reference(version = "1.0.0")
    private UserAuthorizationInfoDubboService userAuthorizationInfoDubboService;
    @Reference(version = "1.0.0")
    private UserBasicInfoDubboService userBasicInfoDubboService;
    @Reference(version = "1.0.0")
    private UserForbidDubboService userForbidDubboService;
    @Reference(version = "1.0.0")
    private UserIdentityDubboService userIdentityDubboService;
    @Reference(version = "1.0.0")
    private UserDataDubboService userDataDubboService;
    @Reference(version = "1.0.0")
    private OrganizationDubboService organizationDubboService;
    @Reference(version = "1.0.0")
    private AccountCompanyDubboService accountCompanyDubboService;
    @Autowired
    private InvestService investService;
    @Autowired
    private AutoBatchInvestService autoBatchInvestService;
    @Autowired
    private InvestFlowConfigLocalService flowConfigLocalService;
    @Autowired
    private ProjectInvestOrderMapperExt projectInvestOrderMapperExt;
    @Autowired
    private UserEvaluationRecordMapperExt userEvaluationRecordMapperExt;
    @Autowired
    private ProjectMapperExt projectMapperExt;
    @Autowired
    private SnowflakeIdWorker snowflakeIdWorker;
    @Autowired
    private ProjectInvestingMapperExt projectInvestingMapperExt;
    @Autowired
    private ProjectInvestorPlanMapperExt projectInvestorPlanMapperExt;
    @Autowired
    private KaoLaInvestorMapperExt kaoLaInvestorMapperExt;
    @Autowired
    private SpeedLoanService speedLoanService;
    @Reference(version = "1.0.0")
    private ActivityPrizeDubboService activityPrizeDubboService;
    @Reference(version = "1.0.0")
    private MoneyTotalDubboService moneyTotalDubboService;
    @Autowired
    private ProjectRateMapperExt projectRateMapperExt;
    @Autowired
    private PrivacyMasks privacyMasks;
    @Autowired
    AdvanceConfigMapperExt advanceConfigMapperExt;
    @Autowired
    private TradeConfigLocalService tradeConfigLocalService;
    @Autowired
    private InvestAddInterestRateConfigMapperExt investAddInterestRateConfigMapperExt;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    private ContractBaseService contractBaseService;
    @Autowired
    private NewbieProjectConfigMapperExt newbieProjectConfigMapper;
    @Autowired
    private IntelligenceInvestService intelligenceInvestService;
    @Autowired
    private NoviceIntelligenceInvestService noviceIntelligenceInvestService;
    @Autowired
    private InvestCommonServer investCommonServer;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private ProjectLocalService projectLocalService;

    @Override
    public InvestOrderResponseDTO invest(InvestDubboRequest investDubboRequest) {
        String userId = investDubboRequest.getUserId();
        AccountBaseResponse accountBaseNoMaster = null;
        if(UserTypeEnum.ORGANIZATION.getValue().equals(investDubboRequest.getInvestUserType())) {
        	accountBaseNoMaster = accountDubboService.getOrgAccount(userId, userId);
        	
        }else {
        	accountBaseNoMaster = accountDubboService.loadNiiwooAccount(userId, UserRoleEnum.INVESTOR);
        }
        AccountBaseResponse accountBase =  accountDubboService.loadAccountByIdFromMaster(accountBaseNoMaster.getAccountId());
        Date expired = new DateTime(new Date()).plusMinutes(10).toDate();
        investService.validateRiskEvaluating(userId);
        return investService.invest(investDubboRequest, accountBase.getAccountId(), accountBase.getAvailableAmount(), expired, accountBase.getTender(), accountBase.getAccountNo());
    }

    @Override
    public InvestCreditResponseDTO investCreditor(InvestCreditDubboRequest investDubboRequest) {
        String userId = investDubboRequest.getUserId();
        AccountBaseResponse accountBase = accountDubboService.loadNiiwooAccount(userId, UserRoleEnum.INVESTOR);
        //订单超时时间 主要用于意外异常订单重试或者网关调用定时重试
        Date expired = new DateTime(new Date()).plusMinutes(10).toDate();
        //验证是否做过风险测评
        investService.validateRiskEvaluating(userId);
        return investService.investCreditor(investDubboRequest, accountBase, expired);
    }

    @Override
    public void investCompleteHandle(Long investOrderId, boolean isSuccess) {
        investService.investCompleteHandle(investOrderId, isSuccess, true, null);
    }

    @Override
    public void investCompleteHandle(Long investOrderId, boolean isSuccess, boolean isAbsolutely, Date queryTime) {
        investService.investCompleteHandle(investOrderId, isSuccess, isAbsolutely, queryTime);
    }

    @Override
    public void investOrderBatchProcess() {
    	//智能投的标不进行定时任务触发订单状态变更
        List<ProjectInvestOrder> list = projectInvestOrderMapperExt.selectDealingList();
        for (ProjectInvestOrder projectInvestOrder : list) {
            try {
                accountInvestDubboService.accountInvestInternalHandle(projectInvestOrder.getId());
            } catch (Exception e) {
                logger.error("投资订单状态变更job异常,investOrderId={}", projectInvestOrder.getId(), e);
            }

        }
    }

    @Override
    public void deleteSoldOutProject() {
        List<ProjectInvesting> projectInvestingList = projectInvestingMapperExt.selectSoldOutList(199, Integer.MAX_VALUE, Byte.valueOf("1"));
        for (ProjectInvesting projectInvesting : projectInvestingList) {
            projectInvestingMapperExt.deleteByPrimaryKey(projectInvesting.getProjectId());
        }
        projectInvestingList = projectInvestingMapperExt.selectSoldOutList(199, Integer.MAX_VALUE, Byte.valueOf("2"));
        for (ProjectInvesting projectInvesting : projectInvestingList) {
            projectInvestingMapperExt.deleteByPrimaryKey(projectInvesting.getProjectId());
        }
    }

    @Override
    public List<InvestOrderDTO> getMyInvestOrderPage(String userId, Integer orderStatus, Integer pageNumber, Integer pageSize) {
        return investService.getMyInvestOrderPage(userId, orderStatus, pageNumber, pageSize);
    }

    @Override
    public InvestEvaluationDTO addInvestEvaluation(String userId, Integer score, Byte isDefOpeartion) {
        return addInvestEvaluation(userId, score, isDefOpeartion, null);
    }

    @Override
    public InvestEvaluationDTO addInvestEvaluation(String userId, Integer score, Byte isDefOpeartion, Byte incomeSource) {
        Date date = new DateTime().monthOfYear().withMinimumValue()
                .dayOfMonth().withMinimumValue()
                .hourOfDay().withMinimumValue()
                .minuteOfHour().withMinimumValue()
                .secondOfMinute().withMinimumValue()
                .millisOfSecond().withMinimumValue().toDate();
        int count = userEvaluationRecordMapperExt.selectCountByUserId(userId, date);

        if (count >= 3) {
            throw new BizException("TRD30001");
        }
        UserEvaluationRecord record = new UserEvaluationRecord();
        record.setId(snowflakeIdWorker.nextId());
        record.setUserId(userId);
        record.setScore(score);
        Byte level = 1;
        if (score >= 41 && score <= 60) {
            level = 2;
        } else if (score >= 61 && score <= 100) {
            level = 3;
        }
        record.setLevel(level);
        record.setIsDefOpeartion(isDefOpeartion);
        if (incomeSource != null) {
            record.setIncomeSource(incomeSource);
        }
        record.setCreateTime(new Date());
        userEvaluationRecordMapperExt.insertSelective(record);

        InvestEvaluationDTO result = new InvestEvaluationDTO();
        result.setScore(score);
        result.setLevel(level);
        result.setIsDefOpeartion(isDefOpeartion);
        result.setCurrentYearTimes(count + 1);
        result.setHadEvaluate(Byte.valueOf("1"));
        try {
            NoviceTaskRecordRequestDTO dto = new NoviceTaskRecordRequestDTO();
            dto.setUserId(userId);
            dto.setTaskType(NoviceTaskPrizeEnum.FRIST_RISK.getCode());
            rabbitTemplate.convertAndSend(RabbitConstant.Exchange.NOVICE_TASK_RECORD, RabbitConstant.RoutingKey.NOVICE_TASK_RECORD, dto);
        } catch (Exception e) {
            log.error("novice_task_activity首次完成风险评测###调用新手任务###请求失败,userId={}, errorMessage={}", userId, e.getMessage());
        }
        return result;
    }

    @Override
    public InvestFlowConfigResponseDTO getSoldOutGuidance(String userId) {
        InvestFlowConfig flowConfig = null;
        if (null == userId) {
            //引导参加运营活动
            flowConfig = flowConfigLocalService.queryByType(InvestFlowConfigTypeEnum.SOLDOUT_ENABLED_AUTO_INVEST);
        } else {
            UserInvestConfig config = autoBatchInvestService.queryUserInvestConfig(userId, InvestWayEnum.AUTO);
            if (config == null || 1 != config.getEnableAuto()) {
                //引导设置自动投资
                flowConfig = flowConfigLocalService.queryByType(InvestFlowConfigTypeEnum.SOLDOUT_DISABLED_AUTO_INVEST);
            } else {
                //引导参加运营活动
                flowConfig = flowConfigLocalService.queryByType(InvestFlowConfigTypeEnum.SOLDOUT_ENABLED_AUTO_INVEST);
            }
        }
        InvestFlowConfigResponseDTO responseDTO = null;
        if (flowConfig != null) {
            responseDTO = new InvestFlowConfigResponseDTO();
            responseDTO.setType(InvestFlowConfigTypeEnum.enumOf(flowConfig.getType()));
            responseDTO.setTitle(flowConfig.getTitle());
            responseDTO.setContent(flowConfig.getContent());
            responseDTO.setButtonText(flowConfig.getButtonText());
            responseDTO.setLink(flowConfig.getLink());
            responseDTO.setIsShow(flowConfig.getIsShow());
        }
        return responseDTO;
    }

    @Override
    public InvestFlowConfigResponseDTO getSoldOutGuidanceTransfer(String userId) {
        InvestFlowConfig flowConfig = flowConfigLocalService.queryByType(InvestFlowConfigTypeEnum.SOLDOUT_TRANSFER_INVEST);
        InvestFlowConfigResponseDTO responseDTO = null;
        if (flowConfig != null) {
            responseDTO = new InvestFlowConfigResponseDTO();
            responseDTO.setType(InvestFlowConfigTypeEnum.enumOf(flowConfig.getType()));
            responseDTO.setTitle(flowConfig.getTitle());
            responseDTO.setButtonText(flowConfig.getButtonText());
            responseDTO.setContent(flowConfig.getContent());
            responseDTO.setLink(flowConfig.getLink());
            responseDTO.setIsShow(flowConfig.getIsShow());
        }
        return responseDTO;
    }



    @Override
    public InvestEvaluationDTO getInvestEvaluationInfo(String userId) {
        UserEvaluationRecord record = userEvaluationRecordMapperExt.selectByUserIdLimitOne(userId);
        if (null == record) {
            return new InvestEvaluationDTO();
        }
        Date date = new DateTime().monthOfYear().withMinimumValue()
                .dayOfMonth().withMinimumValue()
                .hourOfDay().withMinimumValue()
                .minuteOfHour().withMinimumValue()
                .secondOfMinute().withMinimumValue()
                .millisOfSecond().withMinimumValue().toDate();
        int countWithDate = userEvaluationRecordMapperExt.selectCountByUserId(userId, date);

        InvestEvaluationDTO result = new InvestEvaluationDTO();
        result.setHadEvaluate(Byte.valueOf("1"));
        result.setCurrentYearTimes(countWithDate);
        result.setIsDefOpeartion(record.getIsDefOpeartion());
        result.setLevel(record.getLevel());
        result.setSurplusCanInvestAmount(investCommonServer.getSurplusCanInvestAmount(record));  //当前风险等级对应的剩余可投资金额
        result.setScore(record.getScore());
        return result;
    }

    @Override
    public List<FreshInvestingProjectDTO> getInvestingProjectInfo(List<Long> projectIdList) {
        List<FreshInvestingProjectDTO> resultList = new ArrayList<>();
        Set<Long> projectIdSet = new HashSet<>(projectIdList);

        List<ProjectInvesting> projectInvestings = projectInvestingMapperExt.selectListByProjectIdSet(Arrays.asList(projectIdSet.toArray(new Long[projectIdSet.size()])));

        Set<Long> projectIdDBSet = new HashSet<>();
        for (ProjectInvesting projectInvesting : projectInvestings) {
            FreshInvestingProjectDTO dto = new FreshInvestingProjectDTO();
            dto.setProjectId(projectInvesting.getProjectId());
            dto.setRemainAmount(
                    Byte.valueOf("3").equals(projectInvesting.getStatus()) ? BigDecimal.ZERO
                            : projectInvesting.getContractAmount().subtract(projectInvesting.getInvestedAmount()));
            dto.setStatus(BigDecimal.ZERO.compareTo(dto.getRemainAmount()) >= 0 ? Byte.valueOf("1") : Byte.valueOf("0"));  //1-已抢光  0-可投
            resultList.add(dto);
            projectIdDBSet.add(projectInvesting.getProjectId());
        }
        projectIdSet.removeAll(projectIdDBSet);
        if (!projectIdSet.isEmpty()) {
            for (Long projectId : projectIdSet) {
                FreshInvestingProjectDTO dto = new FreshInvestingProjectDTO();
                dto.setProjectId(projectId);
                dto.setRemainAmount(BigDecimal.ZERO);
                dto.setStatus(Byte.valueOf("1"));
                resultList.add(dto);
            }
        }
        return resultList;
    }

    @Override
    public List<InvestedOrderDTO> getProjectInvestOrderList(Long projectId) {
        List<InvestedOrderDTO> resultList = new ArrayList<>();
        Project project = projectMapperExt.selectByPrimaryKey(projectId);
        // 渠道的投资人投资记录处理
        if (project != null && ChannelCodeEnum.KAOLA.getChanelCode().equals(project.getChannelCode())) {
            List<KaoLaInvestor> investors = kaoLaInvestorMapperExt.selectByProjectId(projectId);
            for (KaoLaInvestor investor : investors) {
                InvestedOrderDTO dto = new InvestedOrderDTO();
                /*
                 * 考拉理财 投资人用户id,头像,昵称未在数据库存储
                 */
                dto.setRealName(investor.getRealName());
                dto.setIdCard(investor.getIdCard());
                dto.setChannelCode(ChannelCodeEnum.KAOLA.getFinanceFlag());
                dto.setInvestorNiiwooScore(300);//默认统一为300分
                dto.setAmount(investor.getAmount());
                dto.setInvestTime(investor.getInvestTime());
                resultList.add(dto);
            }
        } else {
            List<ProjectInvestOrder> list = projectInvestOrderMapperExt.selectInvestedList(projectId);

            Set<String> userIdSet = new HashSet<>();
            for (ProjectInvestOrder projectInvestOrder : list) {
                userIdSet.add(projectInvestOrder.getUserId());
            }
            Map<String, UserBasicInfoDTO> userBasicInfoDTOMap = new HashMap<>();
            List<UserBasicInfoDTO> userBasicInfoDTOS = userBasicInfoDubboService.queryListByUserIdSet(userIdSet);
            for (UserBasicInfoDTO userBasicInfoDTO : userBasicInfoDTOS) {
                userBasicInfoDTOMap.put(userBasicInfoDTO.getUserId(), userBasicInfoDTO);
            }

            for (ProjectInvestOrder projectInvestOrder : list) {
                UserBasicInfoDTO userBasicInfoDTO = userBasicInfoDTOMap.get(projectInvestOrder.getUserId());
                InvestedOrderDTO dto = new InvestedOrderDTO();
                dto.setInvestUserId(projectInvestOrder.getUserId());
                dto.setInvestorHeadImage(userBasicInfoDTO.getHeadImage());
                dto.setInvestorNickName(userBasicInfoDTO.getNickName());
                dto.setInvestorGender(userBasicInfoDTO.getGender());
                dto.setInvestorNiiwooScore(userBasicInfoDTO.getNiiwooScore());
                dto.setAmount(projectInvestOrder.getAmount());
                dto.setInvestTime(projectInvestOrder.getCreateTime());
                dto.setChannelCode(ChannelCodeEnum.APP.getFinanceFlag());
                resultList.add(dto);
            }
        }
        return resultList;
    }

    @Override
    public ProjectInvestOrderPageResponse getPageProjectInvestOrderList(ProjectInvestOrderPageRequest request) {
        ProjectInvestOrderPageResponse response = new ProjectInvestOrderPageResponse();

        List<InvestedOrderDTO> dataList = new ArrayList<>();
        int totalRecord = 0;

        Project project = projectMapperExt.selectByPrimaryKey(request.getProjectId());
        // 渠道的投资人投资记录处理
        if (project != null && ChannelCodeEnum.KAOLA.getChanelCode().equals(project.getChannelCode())) {
            totalRecord = kaoLaInvestorMapperExt.queryTotalInvestmentRecord(request.getProjectId());
            if (totalRecord > 0) {
                List<KaoLaInvestor> investors = kaoLaInvestorMapperExt.selectPageByProjectId(request.getProjectId(), request.getOffset(), request.getPageSize());
                for (KaoLaInvestor investor : investors) {
                    InvestedOrderDTO dto = new InvestedOrderDTO();
                    dto.setRealName(investor.getRealName());
                    dto.setIdCard(investor.getIdCard());
                    dto.setChannelCode(ChannelCodeEnum.KAOLA.getFinanceFlag());
                    dto.setInvestorNiiwooScore(300);
                    dto.setAmount(investor.getAmount());
                    dto.setInvestTime(investor.getInvestTime());
                    dataList.add(dto);
                }
            }
        } else {
            totalRecord = projectInvestOrderMapperExt.countInvested(request.getProjectId());
            if (totalRecord > 0) {
                List<ProjectInvestOrder> list = projectInvestOrderMapperExt.selectPageInvestedList(request.getProjectId(), request.getOffset(), request.getPageSize());

                Set<String> userIdSet = new HashSet<>();
                Set<String> orgIdSet = new HashSet<>();
                for (ProjectInvestOrder projectInvestOrder : list) {
                    if(UserTypeEnum.ORGANIZATION.getValue().equals(projectInvestOrder.getInvestorType())) {
                        orgIdSet.add(projectInvestOrder.getUserId());
                    }else {
                        userIdSet.add(projectInvestOrder.getUserId());
                    }

                }

                Map<String, UserBasicInfoDTO> userBasicInfoDTOMap = new HashMap<>();
                Map<String, SimpleOrgInfo> orgInfoDTOMap = new HashMap<>();
                if (CollectionUtils.isNotEmpty(userIdSet)) {
                    List<UserBasicInfoDTO> userBasicInfoDTOS = userBasicInfoDubboService.queryListByUserIdSet(userIdSet);
                    for (UserBasicInfoDTO userBasicInfoDTO : userBasicInfoDTOS) {
                        userBasicInfoDTOMap.put(userBasicInfoDTO.getUserId(), userBasicInfoDTO);
                    }
                }
                if(CollectionUtils.isNotEmpty(orgIdSet)) {
                    List<SimpleOrgInfo> orgs = organizationDubboService.queryListByOrgIdSet(orgIdSet);
                    for (SimpleOrgInfo simpleOrgInfo : orgs) {
                        orgInfoDTOMap.put(simpleOrgInfo.getId()+"", simpleOrgInfo);
                    }
                }
                //企业投资人与个人投资区分
                for (ProjectInvestOrder projectInvestOrder : list) {
                    InvestedOrderDTO dto = new InvestedOrderDTO();
                    if(UserTypeEnum.ORGANIZATION.getValue().equals(projectInvestOrder.getInvestorType())) {
                        SimpleOrgInfo info = orgInfoDTOMap.get(projectInvestOrder.getUserId());
                        dto.setInvestorHeadImage(info.getHeadImg());
                        dto.setInvestorNickName(info.getNickName());
                        dto.setInvestorGender(Byte.valueOf("1"));
                        dto.setInvestorNiiwooScore(300);
                    }else {
                        UserBasicInfoDTO userBasicInfoDTO = userBasicInfoDTOMap.get(projectInvestOrder.getUserId());
                        dto.setInvestorHeadImage(userBasicInfoDTO.getHeadImage());
                        dto.setInvestorNickName(userBasicInfoDTO.getNickName());
                        dto.setInvestorGender(userBasicInfoDTO.getGender());
                        dto.setInvestorNiiwooScore(userBasicInfoDTO.getNiiwooScore());
                    }
                    dto.setInvestUserId(projectInvestOrder.getUserId());
                    dto.setAmount(projectInvestOrder.getAmount());
                    dto.setInvestTime(projectInvestOrder.getCreateTime());
                    dto.setChannelCode(ChannelCodeEnum.APP.getFinanceFlag());
                    dataList.add(dto);
                }
            }
        }

        response.setTotalRecord(totalRecord);
        response.setDataList(dataList);

        return response;
    }

    @Override
    public List<InvestingProjectDTO> getInvestingProjectListGroupByDeadLine(String channelCode) {
        List<InvestingProjectDTO> resultList = new ArrayList<>();
        Set<Integer> deadlineSet = speedLoanService.listDeadlines();
        if (StringUtils.isBlank(channelCode)) channelCode = "app";
        for (Integer deadline : deadlineSet) {
            ProjectInvesting projectInvesting = projectInvestingMapperExt.selectListGroupByDeadLine(deadline, channelCode);
            if (projectInvesting != null) {
                InvestingProjectDTO investingProjectDTO = this.convertToInvestingProjectDTO(projectInvesting);
                resultList.add(investingProjectDTO);
            }
        }
        //completeLoanTimes(resultList);
        investService.completeLoanTimes(resultList);
        return resultList;
    }

    @Override
    public PageResponseDTO<InvestingProjectDTO> getInvestingProjectPage(InvestingProjectPageRequestDTO investingProjectPageRequestDTO, boolean isCheckProject) {
        PageResponseDTO<InvestingProjectDTO> dtoPageResponseDTO = new PageResponseDTO<>();

        List<InvestingProjectDTO> result = new ArrayList<>();
        //如果是app 则保持线上逻辑，大V客户 不限制多少数量
        String maxSizeAsString = null;
        if("APP".equals(investingProjectPageRequestDTO.getChannelCode())){
            TradeConfigEnum key = TradeConfigEnum.RETAIL_PROJECT_SHOW_SIZE;
            //查询信用标，抵押标的 类型 配置的上线数
            /*if (investingProjectPageRequestDTO.getFiterType() == 1) {
                key = TradeConfigEnum.CREDIT_PROJECT_SHOW_SIZE;
            } else {
                key = TradeConfigEnum.MORTGAGE_PROJECT_SHOW_SIZE;
            }*/
            maxSizeAsString = redisTemplate.opsForValue().get(key.getConfigKey());
            if (Objects.isNull(maxSizeAsString)) {
                maxSizeAsString = tradeConfigLocalService.selectTradeConfigByEmun(key);
            }
            //控制最大查询条数
            if (Objects.nonNull(maxSizeAsString)) {
                int maxSize = Integer.valueOf(maxSizeAsString);
                // 只查询配置的条数
                if (maxSize <= investingProjectPageRequestDTO.getOffset()) {
                    return dtoPageResponseDTO;
                }
                if (maxSize <= investingProjectPageRequestDTO.getOffset() + investingProjectPageRequestDTO.getPageSize()) {
                    investingProjectPageRequestDTO.setPageSize(maxSize - investingProjectPageRequestDTO.getOffset());
                }
            }
        }
        investingProjectPageRequestDTO.setTransferKey(TradeConfigEnum.DEBT_TRANSFER_TAG_PERIOD.getConfigKey());
        //先查询 投资记录表，如果没有数据，按照产品要求，查询标的表最近三个月的历史数据
        //联动配置，在后台配置好的，通过配置的期限查询，有可能该期限的标 状态已经不是可投资的状态，在t_tc_project_investing最多保留200条
        //有可能查询不到，所以查询标的表，查询出满标的历史记录
        List<ProjectInvesting> list = isCheckProject ? projectMapperExt.selectPageByParamsByProject(investingProjectPageRequestDTO)
                : projectInvestingMapperExt.selectPageByParams(investingProjectPageRequestDTO);
        if(CollectionUtils.isEmpty(list)){
            return dtoPageResponseDTO;
        }
        Integer count = isCheckProject ? projectMapperExt.selectPageByParamsByProjectCount(investingProjectPageRequestDTO) :
                projectInvestingMapperExt.selectPageByParamsCount(investingProjectPageRequestDTO);
        //实时找到用户信息列表
        Set<String> stringList = list.stream().map(ProjectInvesting::getBorrowUserId).collect(Collectors.toSet());
        List<UserBasicInfoDTO> dtoList = userBasicInfoDubboService.queryListByUserIdSet(stringList);
        //查询加息的标
        List<InvestAddInterestRateConfig> configs = investAddInterestRateConfigMapperExt.selectAll();
        List<Long> projectIds = list.stream().map(ProjectInvesting::getProjectId).collect(Collectors.toList());
        List<Project> projectList = projectMapperExt.selectListByProjectIdSet(projectIds);
        for (ProjectInvesting projectInvesting : list) {
            for (UserBasicInfoDTO userBasicInfoDTO : dtoList) {
                if(userBasicInfoDTO.getUserId().equals(projectInvesting.getBorrowUserId())){
                    projectInvesting.setBorrowNickName(userBasicInfoDTO.getNickName());
                    projectInvesting.setBorrowHeadImage(userBasicInfoDTO.getHeadImage());
                    break;
                }
            }
            InvestingProjectDTO dto = this.convertToInvestingProjectDTO(projectInvesting);
            //找到加息的活动
            for (InvestAddInterestRateConfig config : configs) {
                if(config.getId().equals(projectInvesting.getActivityId())){
                    dto.setInterestAddTitle(config.getTitle());
                    dto.setInterestAddRate(projectInvesting.getActivityRaiseRate().multiply(BigDecimal.valueOf(100)));
                    break;
                }
            }
            // 鸿特机构标的，若为“共借”借款，散标列表、标的详情页和投资订单页的授信类型不显示  (是否主借人?0.否;1.是)
            for (Project project : projectList) {
                if(project.getProjectId().equals(dto.getProjectId())){
                    dto.setLoanType(project.getLoanType()); //借款类型
                    dto.setLoanTypeDesc(LoanTypeEnum.enumOf(dto.getLoanType()).getDesc());
                    dto.setIsMasterBorrower(project.getIsMasterBorrower());
                    result.add(dto);
                    break;
                }
            }

        }
        //成功借款次数
        //completeLoanTimes(result);
        investService.completeLoanTimes(result);
        dtoPageResponseDTO.setItems(result);
        if("APP".equals(investingProjectPageRequestDTO.getChannelCode()) && count > Integer.parseInt(maxSizeAsString)){
            dtoPageResponseDTO.measureTotalPage(Integer.parseInt(maxSizeAsString),investingProjectPageRequestDTO.getPageSize());
        }else{
            dtoPageResponseDTO.measureTotalPage(count,investingProjectPageRequestDTO.getPageSize());
        }

        return dtoPageResponseDTO;
    }

    /**
     * 返利投查询可投资信息记录
     *
     * @param investingProjectPageRequestDTO
     * @return
     */
    @Override
    public InvestingProjectPageResponseDTO getFanLiInvestingProjectPage(FanLiInvestingProjectPageRequestDTO investingProjectPageRequestDTO) {
        InvestingProjectPageResponseDTO result = new InvestingProjectPageResponseDTO();

        List<BidListDTO> bidList = new ArrayList<>();
        int offset = investingProjectPageRequestDTO.getOffset();
        int pageSize = investingProjectPageRequestDTO.getPageSize();
        try {
            List<ProjectInvesting> list = projectInvestingMapperExt.selectFanLiInvestPageByParams(offset, pageSize,ChannelCodeEnum.APP.getChanelCode());
            result.setSuccess(true);
            result.setMessage("查询成功");
            int totalCount = projectInvestingMapperExt.accountFanLiInvestPageByParams(ChannelCodeEnum.APP.getChanelCode());
            result.setTotal_count(totalCount);
            for (ProjectInvesting projectInvesting : list) {
                BidListDTO bidListDTO = new BidListDTO();
                bidListDTO.setBid_id(projectInvesting.getProjectId().toString());
                bidListDTO.setStatus(projectInvesting.getStatus());
                bidListDTO.setName(projectInvesting.getTitle() + "(" + ProjectCreditTypeEnum.typeOf(projectInvesting.getCreditType()).getTag() + ")");
                bidListDTO.setIs_new_user(false);
                bidListDTO.setPc_url("");
                bidListDTO.setMobile_url("");
                bidListDTO.setTotal_amount(projectInvesting.getContractAmount().doubleValue());
                bidListDTO.setRemain_amount((projectInvesting.getContractAmount().subtract(projectInvesting.getInvestedAmount())).doubleValue());
                bidListDTO.setMin_invest_amount(100.0);
                bidListDTO.setIncrement_amount(100.0);
                bidListDTO.setDuration(projectInvesting.getDeadline());
                if (projectInvesting.getDeadlineUnit() == 1) {
                    bidListDTO.setDuration_unit(30);
                } else if (projectInvesting.getDeadlineUnit() == 2) {
                    bidListDTO.setDuration_unit(1);
                } else {
                    bidListDTO.setDuration_unit(30);
                }
                bidListDTO.setIs_lockin_bid(false);
                bidListDTO.setMax_duration(projectInvesting.getDeadline());
                if (projectInvesting.getDeadlineUnit() == 1) {
                    bidListDTO.setMax_duration_unit(30);
                } else if (projectInvesting.getDeadlineUnit() == 2) {
                    bidListDTO.setMax_duration_unit(1);
                } else {
                    bidListDTO.setMax_duration_unit(30);
                }
                bidListDTO.setInterest_rate(projectInvesting.getBorrowRate().doubleValue());
                switch (projectInvesting.getRepaymentType()) {
                    case 1:
                        bidListDTO.setRepayment_type(3);
                        break;
                    case 2:
                        bidListDTO.setRepayment_type(4);
                        break;
                    case 3:
                        bidListDTO.setRepayment_type(1);
                        break;
                }
                bidList.add(bidListDTO);
            }
        } catch (Exception e) {
            result.setSuccess(false);
            result.setMessage(e.getMessage());
        }
        result.setBid_list(bidList);
        return result;
    }

    /**
     * 返利投查询可投资标的详情信息
     *
     * @param projectId
     * @return
     */
    @Override
    public FanLiProjectDetailResponseDTO getFanLiInvestingDetailPage(Long projectId) {
        FanLiProjectDetailResponseDTO result = new FanLiProjectDetailResponseDTO();
        try {
            Project project = projectMapperExt.selectByPrimaryKey(projectId);
            if (project != null) {
                Bid bid = new Bid();
                result.setSuccess(true);
                result.setMessage("查询成功");
                bid.setBid_id(project.getProjectId().toString());
                //项目状态
                switch (project.getStatus()) {
                    case 2:
                        bid.setStatus(1);
                        break;
                    case 3:
                        bid.setStatus(2);
                        break;
                    case 4:
                        bid.setRepayment_type(3);
                        break;
                    case 1:
                        bid.setRepayment_type(4);
                        break;
                    case 5:
                        bid.setRepayment_type(-1);
                        break;
                }
                bid.setName(project.getTitle() + "(" + ProjectCreditTypeEnum.typeOf(project.getCreditType()).getTag() + ")");
                bid.setIs_new_user(false);
                bid.setPc_url("");
                bid.setMobile_url("");
                bid.setTotal_amount(project.getContractAmount().doubleValue());
                bid.setRemain_amount((project.getContractAmount().subtract(project.getInvestedAmount())).doubleValue());
                bid.setMin_invest_amount(100.0);
                bid.setIncrement_amount(100.0);
                bid.setDuration(project.getDeadline());
                if (project.getDeadlineUnit() == 1) {
                    bid.setDuration_unit(30);
                } else if (project.getDeadlineUnit() == 2) {
                    bid.setDuration_unit(1);
                }
                bid.setIs_lockin_bid(false);
                bid.setMax_duration(project.getDeadline());
                if (project.getDeadlineUnit() == 1) {
                    bid.setMax_duration_unit(30);
                } else if (project.getDeadlineUnit() == 2) {
                    bid.setMax_duration_unit(1);
                }
                bid.setInterest_rate(project.getBorrowRate().doubleValue());
                switch (project.getRepaymentType()) {
                    case 1:
                        bid.setRepayment_type(3);
                        break;
                    case 2:
                        bid.setRepayment_type(4);
                        break;
                    case 3:
                        bid.setRepayment_type(1);
                        break;
                }
                if (project.getFullSuccessTime() == null) {
                    bid.setFull_time(null);
                } else {
                    bid.setFull_time(project.getFullSuccessTime().toString());
                }
                result.setBid(bid);
            }
            result.setSuccess(false);
            result.setMessage("不存在改标的信息");
        } catch (Exception e) {
            result.setSuccess(false);
            result.setMessage(e.getMessage());
        }
        return result;
    }




    /**
     * 持久层对象转为DTO
     *
     * @param projectInvesting
     * @return
     */
    private InvestingProjectDTO convertToInvestingProjectDTO(ProjectInvesting projectInvesting) {
        InvestingProjectDTO dto = new InvestingProjectDTO();
        dto.setProjectId(projectInvesting.getProjectId());
        dto.setProjectType(projectInvesting.getType());
        dto.setBorrowerUserId(projectInvesting.getBorrowUserId());
        dto.setBorrowerHeadImage(projectInvesting.getBorrowHeadImage());
        dto.setBorrowerNickName(projectInvesting.getBorrowNickName());
        dto.setBorrowerGender(projectInvesting.getBorrowGender());
        dto.setBorrowerNiiwooScore(projectInvesting.getBorrowNiiwooScore());
        dto.setCity(projectInvesting.getLoanCity());
        dto.setArea(projectInvesting.getLoanArea());
        dto.setPublishTime(ProjectUtil.getProjectPublishtime(projectInvesting.getPublishTime()));
        dto.setTitle(projectInvesting.getTitle().replaceAll("借款用途：","").replaceAll("借款用于",""));
        dto.setBorrowRate(projectInvesting.getBorrowRate());
        dto.setDeadline(projectInvesting.getDeadline());
        dto.setDeadlineUnit(projectInvesting.getDeadlineUnit());
        dto.setContractAmount(projectInvesting.getContractAmount());
        dto.setInvestingAmount(projectInvesting.getContractAmount().subtract(projectInvesting.getInvestedAmount()));
        dto.setBaseInvestMoney(new BigDecimal("100"));
        dto.setRepaymentType(projectInvesting.getRepaymentType());
        // 标的状态：1可投，2已抢光
        Integer projectStatus = null;
        if (Byte.valueOf("3").equals(projectInvesting.getStatus())) {
            projectStatus = 2;
        } else if (projectInvesting.getContractAmount().compareTo(projectInvesting.getInvestedAmount()) == 0) {
            projectStatus = 2;
        } else if (Byte.valueOf("5").equals(projectInvesting.getStatus())) {
            projectStatus = 2;
        } else {
            projectStatus = 1;
        }
        dto.setProjectStatus(projectStatus);
        dto.setCreditType(projectInvesting.getCreditType());
        dto.setBorrowerType(projectInvesting.getBorrowerType());
        return dto;
    }

    /*private void completeLoanTimes(List<InvestingProjectDTO> list) {
        Set<String> borrowUserIdSet = new HashSet<>();
        for (InvestingProjectDTO investingProjectDTO : list) {
            borrowUserIdSet.add(investingProjectDTO.getBorrowerUserId());
        }

        if (!borrowUserIdSet.isEmpty()) {
            List<UserSuccessProjectCountDTO> userSuccessProjectCountDTOS = projectMapperExt.selectUserSuccessProjectCountDTOList(Arrays.asList(borrowUserIdSet.toArray(new String[borrowUserIdSet.size()])));
            Map<String, Integer> userIdSuccessCountMap = new HashMap<>();
            for (UserSuccessProjectCountDTO userSuccessProjectCountDTO : userSuccessProjectCountDTOS) {
                userIdSuccessCountMap.put(userSuccessProjectCountDTO.getUserId(), userSuccessProjectCountDTO.getSuccessCount());
            }
            for (InvestingProjectDTO investingProjectDTO : list) {
                Integer successCount = userIdSuccessCountMap.get(investingProjectDTO.getBorrowerUserId());
                if (null != successCount) {
                    if (successCount >= 1) {
                        investingProjectDTO.setLoanTimes(successCount - 1);
                    } else {
                        investingProjectDTO.setLoanTimes(0);
                    }
                }
            }
        }
    }*/

    @Override
    public List<InvestingProjectDTO> getRecomendProjectList(Long projectId, String borrowUserId, String channelCode) {
        Project project = projectMapperExt.selectByUserIdAndProjectId(borrowUserId, projectId);
        if (null == project) {
            return new ArrayList<>();
        }
        Byte projectType = project.getType();
        BigDecimal borrowRate = project.getBorrowRate();
        Integer deadline = project.getDeadline();
        Byte deadlineUnit = project.getDeadlineUnit();
        List<ProjectInvesting> list1 = projectInvestingMapperExt.selectRecommendListByParams(channelCode, projectType, borrowRate, deadline, deadlineUnit);
        if (list1.size() < 10) {
            List<ProjectInvesting> list2 = projectInvestingMapperExt.selectRecommendListByParams(channelCode, projectType, borrowRate, null, null);
            list1.addAll(list2);
            List<ProjectInvesting> list3 = projectInvestingMapperExt.selectRecommendListByParams(channelCode, projectType, null, deadline, deadlineUnit);
            list1.addAll(list3);
        }
        List<InvestingProjectDTO> resultList = new ArrayList<>();
        Set<Long> projectIdSet = new HashSet<>();
        for (ProjectInvesting projectInvesting : list1) {
            if (projectIdSet.contains(projectInvesting.getProjectId())) {
                continue;
            }

            projectIdSet.add(projectInvesting.getProjectId());
            InvestingProjectDTO dto = this.convertToInvestingProjectDTO(projectInvesting);
            resultList.add(dto);

            if (projectIdSet.size() == 10) {
                break;
            }
        }
        //completeLoanTimes(resultList);
        investService.completeLoanTimes(resultList);
        return resultList;
    }

    @Override
    public List<SysInvestConfigDTO> querySysInvestConfig() {
        return autoBatchInvestService.querySysInvestConfigDTOList();
    }

    @Override
    public List<InvestingQueryCondtionConfigDTO> queryInvestingQueryCondtionConfig(BorrowerTypeEnum borrowerType) {
        return investService.queryInvestingQueryCondtionConfig(borrowerType);
    }

    @Override
    public InvestSuccessInfoDTO getInvestSuccessInfo(Long investOrderId) {
        ProjectInvestOrder projectInvestOrderFromMaster = investService.getProjectInvestOrderFromMaster(investOrderId);
        InvestSuccessInfoDTO result = new InvestSuccessInfoDTO();
        result.setStatus(projectInvestOrderFromMaster.getStatus());
        result.setInvestAmount(projectInvestOrderFromMaster.getAmount());
        result.setInterest(projectInvestOrderFromMaster.getInterest().add(projectInvestOrderFromMaster.getAddInterest()));
        // 如果使用了红包
        if (null != projectInvestOrderFromMaster.getPrizeId()) {
            // 获取红包名称
            result.setIsPrizeUsed(Byte.valueOf("1"));
            result.setPrizeName(projectInvestOrderFromMaster.getPrizeName());
        }
        AccountBaseResponse accountBase = null;
        if(UserTypeEnum.ORGANIZATION.getValue().equals(projectInvestOrderFromMaster.getInvestorType())) {
            accountBase = accountDubboService.getOrgAccount(projectInvestOrderFromMaster.getUserId(), projectInvestOrderFromMaster.getUserId());
        }else {
            accountBase = accountDubboService.loadNiiwooAccount(projectInvestOrderFromMaster.getUserId(), UserRoleEnum.INVESTOR);
        }

        result.setTender(accountBase.getTender());
        ProjectInvesting projectInvesting = projectInvestingMapperExt.selectByPrimaryKey(projectInvestOrderFromMaster.getProjectId());
        if (null == projectInvesting || Byte.valueOf("3").equals(projectInvesting.getStatus())) {
            result.setRemainingAmount(BigDecimal.ZERO);
        } else {
            result.setRemainingAmount(projectInvesting.getContractAmount().subtract(projectInvesting.getInvestedAmount()));
        }
        result.setUserId(projectInvestOrderFromMaster.getUserId());
        int successCount = projectInvestOrderMapperExt.selectSuccessCountByUserId(projectInvestOrderFromMaster.getUserId());
        if (successCount > 3) {
            result.setIsShowPrompt(Byte.valueOf("0"));
        } else {
            result.setIsShowPrompt(Byte.valueOf("1"));
        }
        return result;
    }

    @Override
    public InvestOrderSimpleInfoResponseDTO getInvestOrderSimpleInfo(Long investOrderId) {
        ProjectInvestOrder projectInvestOrder = projectInvestOrderMapperExt.selectByPrimaryKey(investOrderId);
        InvestOrderSimpleInfoResponseDTO dto = new InvestOrderSimpleInfoResponseDTO();
        dto.setBorrowerHeadImage(projectInvestOrder.getBorrowHeadImage());
        dto.setBorrowerUserId(projectInvestOrder.getBorrowUserId());
        dto.setOrderStatus(projectInvestOrder.getEvolutionStatus());
        dto.setProjectId(projectInvestOrder.getProjectId());
        dto.setProjectTitle(ProjectInfoUtil.getLoanUsage(projectInvestOrder.getTitle()));
        dto.setPublishTime(projectInvestOrder.getPublishTime());
        Project project = projectMapperExt.selectByUserIdAndProjectId(projectInvestOrder.getBorrowUserId(), projectInvestOrder.getProjectId());
        dto.setFullSuccessDate(project.getFullSuccessTime());
        dto.setBorrowerType(project.getBorrowerType());
        return dto;
    }

    @Override
    public void investCancelSuccess(Long investOrderId) {
        investService.investCancelSuccess(investOrderId, InvestOrderCloseReasonEnum.PAY_TIMEOUT);
    }

    @Override
    public void investCancelSuccess(Long investOrderId, InvestOrderCloseReasonEnum closeReason) {
        investService.investCancelSuccess(investOrderId, closeReason);
    }
    @Override
    public void batchInvestCancel() {
        List<ProjectInvestCancelOrder> list = investService.getInvestCancelingList();
        for (ProjectInvestCancelOrder projectInvestCancelOrder : list) {
            try {
                investService.investCancel(projectInvestCancelOrder.getId(), InvestOrderCloseReasonEnum.INVEST_OVERTIME);
            } catch (Exception e) {
                logger.error("计划任务撤投失败，{}", projectInvestCancelOrder.getId(), e);
            }
        }
    }

    @Override
    public FastLoanContractResponseDTO getFastLoanContractInfo(ContractRequestDTO contractRequestDTO, String userId) {
        Long projectId = contractRequestDTO.getProjectId();
        FastLoanContractResponseDTO result = new FastLoanContractResponseDTO();
        Project project = projectMapperExt.selectByUserIdAndProjectId(contractRequestDTO.getBorrowerUserId(), projectId);
        // 合同
        result.setContractNo("b_" + projectId);
        result.setAmount(project.getContractAmount());
        result.setDeadline(project.getDeadline());
        result.setBorrowRate(project.getBorrowRate());

        BigDecimal loanInterest = BigDecimal.ZERO;
        List<RepaymentPlanDTO> repaymentPlan = RepaymentPlanContext.getRepaymentPlan(RepaymentTypeEnum.enumOf(project.getRepaymentType()), project.getType(), project.getContractAmount(),
                project.getBorrowRate(), project.getDeadline(), PeriodUnitEnum.enumOf(project.getDeadlineUnit()), new Date());
        for (RepaymentPlanDTO repaymentPlanDTO : repaymentPlan) {
            loanInterest = loanInterest.add(repaymentPlanDTO.getInterest());
        }
        result.setLoanInterest(loanInterest);

        result.setRepaymentType(RepaymentTypeEnum.enumOf(project.getRepaymentType()).getDesc());
        result.setProjectTitle(project.getTitle().replaceAll("借款用途：","").replaceAll("借款用于",""));
        result.setRefundDate(null == project.getFullSuccessTime() ? null : new DateTime(project.getFullSuccessTime())
                .plusMonths(project.getDeadline()).minusDays(1)
                .withHourOfDay(0).withMinuteOfHour(0).withSecondOfMinute(0).withMillisOfSecond(0).toDate());
        result.setPenaltyRate(project.getPenaltyRate());
        // 平台管理费
        BigDecimal platformManageFeeTotal = project.getContractAmount().multiply(project.getManageRate())
                .setScale(AmountHandleConstant.CALCULATE_PRECISION_TWO, BigDecimal.ROUND_HALF_EVEN);
        result.setPlatformManagementFee(platformManageFeeTotal);
        // 担保服务费
        BigDecimal guaranteeServiceFee = project.getContractAmount().multiply(project.getGuaranteeRate())
                .setScale(AmountHandleConstant.CALCULATE_PRECISION_TWO, BigDecimal.ROUND_HALF_EVEN);
        result.setGuaranteeServiceFee(guaranteeServiceFee);
        result.setEffectiveTime(project.getFullSuccessTime());

        // 丙
        SimpleOrgInfo guarantee;
        if(project.getGuaranteeCompanyOrgId() == null) {
            AdvanceConfig advanceConfig = advanceConfigMapperExt.selectByPrimaryKey(project.getOrgId());
            guarantee = organizationDubboService.getByOrgId(advanceConfig.getUserId());
        } else {
            guarantee = organizationDubboService.getByOrgId(project.getGuaranteeCompanyOrgId());
        }
        if(guarantee != null){
            result.getCPart().setEmail(guarantee.getEmail());
            result.getCPart().setName(guarantee.getOrganizationName());
            result.getCPart().setInstitutionalReditCode(privacyMasks.maskInstitutionalReditCode(StringUtils.isBlank(guarantee.getUnifiedSocialCreditCode()) ? guarantee.getCharterCode() : guarantee.getUnifiedSocialCreditCode()));// 脱敏
        }

        // 丁
        result.getDPart().setName("深圳市你我金融信息服务有限公司");
        result.getDPart().setAddress("广东省深圳市南山区科技园北区乌石头路8号天明科技大厦主楼11楼、12楼1202室");

        List<InvestorContractDTO> investorContractDTOs = contractBaseService.getInvestUserInfoFromInvestorOrder(projectId);
        for (InvestorContractDTO projectInvestOrder : investorContractDTOs) {
            FastLoanContractResponseDTO.APart aPart = new FastLoanContractResponseDTO.APart();
            if (userId.equals(projectInvestOrder.getInvestUserId())) {
                aPart.setName(projectInvestOrder.getInvestUserName());
                aPart.setIdCard(contractBaseService.maskCodeNoMask(projectInvestOrder.getInvestorIdCard(), projectInvestOrder.getInvestorType() == 2));// 解密
            } else {
                aPart.setName(contractBaseService.maskName(projectInvestOrder.getInvestUserName()));// 打码
                aPart.setIdCard(contractBaseService.maskCode(projectInvestOrder.getInvestorIdCard(), projectInvestOrder.getInvestorType() == 2));// 解密脱敏
            }
            aPart.setAmount(projectInvestOrder.getInvestAmount());
            result.getAPartList().add(aPart);
        }
        if (Byte.valueOf("1").equals(contractRequestDTO.getAddInvestor())) {
            FastLoanContractResponseDTO.APart aPart = new FastLoanContractResponseDTO.APart();
            InvestorContractDTO investOrderContractDTO = contractBaseService.getCurrentUserContractDTO(userId);
            if (null != investOrderContractDTO) {
                aPart.setName(investOrderContractDTO.getInvestUserName());
                aPart.setIdCard(StringUtils.isBlank(investOrderContractDTO.getInvestorIdCard()) ? null : investOrderContractDTO.getInvestorIdCard());
            }
            aPart.setAmount(contractRequestDTO.getAddAmount());

            result.getAPartList().add(aPart);
        }

        // 乙方
        StringBuilder address = new StringBuilder();
        address.append(project.getLoanProvince()).append(project.getLoanCity()).append(project.getLoanArea());
        result.getBPart().setAddress(address.toString());
        UserPersonalDubboInfoDTO userPersonalDubboInfoDTO = userDataDubboService.userPersonalInfo(project.getBorrowUserId());
        result.getBPart().setEmail(null == userPersonalDubboInfoDTO ? null : userPersonalDubboInfoDTO.getEmail());
        if (userId.equals(project.getBorrowUserId())) {
            result.getBPart().setName(project.getBorrowUserName());
            result.getBPart().setIdCard(StringUtils.isBlank(project.getBorrowIdCard()) ? null : privacyMasks.decryptPrivacy(project.getBorrowIdCard()));// 解密
        } else {
            result.getBPart().setName(project.getBorrowUserName().substring(0, 1)
                    + project.getBorrowUserName().replaceAll(".", "*").substring(1));
            result.getBPart().setIdCard(StringUtils.isBlank(project.getBorrowIdCard()) ? null : privacyMasks.maskIdCardSixTwo(privacyMasks.decryptPrivacy(project.getBorrowIdCard())));// 解密脱敏
        }
        return result;
    }

    @Override
    public OrgLoanContractResponseDTO getOrgLoanContractInfo(ContractRequestDTO contractRequestDTO, String userId) {
        Long projectId = contractRequestDTO.getProjectId();
        OrgLoanContractResponseDTO result = new OrgLoanContractResponseDTO();
        Project project = projectMapperExt.selectByUserIdAndProjectId(contractRequestDTO.getBorrowerUserId(), projectId);
        // 合同
        result.setContractNo("b_" + projectId);
        result.setAmount(project.getContractAmount());
        result.setDeadline(project.getDeadline());
        result.setDeadlineUnit(project.getDeadlineUnit());
        result.setBorrowRate(project.getBorrowRate().multiply(new BigDecimal(AmountHandleConstant.HUNDRED))
                .setScale(AmountHandleConstant.CALCULATE_PRECISION_TWO, BigDecimal.ROUND_HALF_EVEN));
        result.setPenaltyRate(project.getPenaltyRate().multiply(new BigDecimal(AmountHandleConstant.HUNDRED))
                .setScale(AmountHandleConstant.CALCULATE_PRECISION_TWO, BigDecimal.ROUND_HALF_EVEN));
        BigDecimal loanInterest = BigDecimal.ZERO;
        List<RepaymentPlanDTO> repaymentPlan = RepaymentPlanContext.getRepaymentPlan(RepaymentTypeEnum.enumOf(project.getRepaymentType()), project.getType(), project.getContractAmount(),
                project.getBorrowRate(), project.getDeadline(), PeriodUnitEnum.enumOf(project.getDeadlineUnit()), new Date());
        for (RepaymentPlanDTO repaymentPlanDTO : repaymentPlan) {
            loanInterest = loanInterest.add(repaymentPlanDTO.getInterest());
        }
        result.setLoanInterest(loanInterest);

        result.setRepaymentType(RepaymentTypeEnum.enumOf(project.getRepaymentType()).getDesc());
        result.setProjectTitle(project.getTitle().replaceAll("借款用途：","").replaceAll("借款用于",""));


        // 平台管理费
        BigDecimal platformManageFeeTotal = project.getContractAmount().multiply(project.getManageRate())
                .setScale(AmountHandleConstant.CALCULATE_PRECISION_TWO, BigDecimal.ROUND_HALF_EVEN);
        result.setPlatformManagementFee(platformManageFeeTotal);
        // 担保服务费
        BigDecimal guaranteeServiceFee = project.getContractAmount().multiply(project.getGuaranteeRate())
                .setScale(AmountHandleConstant.CALCULATE_PRECISION_TWO, BigDecimal.ROUND_HALF_EVEN);
        result.setGuaranteeServiceFee(guaranteeServiceFee);
        result.setEffectiveTime(project.getFullSuccessTime());

        BigDecimal platformManagerFeeYear = BigDecimal.ZERO;
        BigDecimal guaranteeRateYear = BigDecimal.ZERO;

        BigDecimal platformManagerRateDay = BigDecimal.ZERO;
        BigDecimal guaranteeRateDay = BigDecimal.ZERO;
        Date lastRefundDate = null;

        PeriodUnitEnum periodUnitEnum = PeriodUnitEnum.enumOf(project.getDeadlineUnit());
        switch (periodUnitEnum) {
            case MONTH:
                lastRefundDate = DateUtils.addDays(DateUtils.addMonths(project.getFullSuccessTime() == null ? new Date() : project.getFullSuccessTime(), project.getDeadline()), -1);
                platformManagerFeeYear = project.getManageRate().multiply(new BigDecimal(AmountHandleConstant.HUNDRED)).divide(BigDecimal.valueOf(project.getDeadline()),
                        MathContext.DECIMAL128).multiply(new BigDecimal(AmountHandleConstant.YEAR_OF_MONTH)).setScale(AmountHandleConstant.CALCULATE_PRECISION_TWO, BigDecimal.ROUND_HALF_EVEN);
                guaranteeRateYear = project.getGuaranteeRate().multiply(new BigDecimal(AmountHandleConstant.HUNDRED)).divide(BigDecimal.valueOf(project.getDeadline()),
                        MathContext.DECIMAL128).multiply(new BigDecimal(AmountHandleConstant.YEAR_OF_MONTH)).setScale(AmountHandleConstant.CALCULATE_PRECISION_TWO, BigDecimal.ROUND_HALF_EVEN);

                platformManagerRateDay = project.getManageRate().multiply(new BigDecimal(AmountHandleConstant.HUNDRED)).divide(BigDecimal.valueOf(project.getDeadline()),
                        MathContext.DECIMAL128).multiply(new BigDecimal(AmountHandleConstant.YEAR_OF_MONTH)).divide(BigDecimal.valueOf(AmountHandleConstant.YEAR_OF_DAY),
                        MathContext.DECIMAL128).setScale(4, BigDecimal.ROUND_HALF_EVEN);
                guaranteeRateDay = project.getGuaranteeRate().multiply(new BigDecimal(AmountHandleConstant.HUNDRED)).divide(BigDecimal.valueOf(project.getDeadline()),
                        MathContext.DECIMAL128).multiply(new BigDecimal(AmountHandleConstant.YEAR_OF_MONTH)).divide(BigDecimal.valueOf(AmountHandleConstant.YEAR_OF_DAY),
                        MathContext.DECIMAL128).setScale(4, BigDecimal.ROUND_HALF_EVEN);
                break;
            case DAY:
                lastRefundDate = DateUtils.addDays(project.getFullSuccessTime() == null ? new Date() : project.getFullSuccessTime(), project.getDeadline());
                platformManagerFeeYear = project.getManageRate().multiply(new BigDecimal(AmountHandleConstant.HUNDRED)).divide(BigDecimal.valueOf(project.getDeadline()),
                        MathContext.DECIMAL128).multiply(new BigDecimal(AmountHandleConstant.YEAR_OF_DAY)).setScale(AmountHandleConstant.CALCULATE_PRECISION_TWO, BigDecimal.ROUND_HALF_EVEN);
                guaranteeRateYear = project.getGuaranteeRate().multiply(new BigDecimal(AmountHandleConstant.HUNDRED)).divide(BigDecimal.valueOf(project.getDeadline()),
                        MathContext.DECIMAL128).multiply(new BigDecimal(AmountHandleConstant.YEAR_OF_DAY)).setScale(AmountHandleConstant.CALCULATE_PRECISION_TWO, BigDecimal.ROUND_HALF_EVEN);

                platformManagerRateDay = project.getManageRate().multiply(new BigDecimal(AmountHandleConstant.HUNDRED)).divide(BigDecimal.valueOf(project.getDeadline()),
                        MathContext.DECIMAL128).setScale(4, BigDecimal.ROUND_HALF_EVEN);
                guaranteeRateDay = project.getGuaranteeRate().multiply(new BigDecimal(AmountHandleConstant.HUNDRED)).divide(BigDecimal.valueOf(project.getDeadline()),
                        MathContext.DECIMAL128).setScale(4, BigDecimal.ROUND_HALF_EVEN);
                break;

            default:
                break;
        }
        result.setRefundDate(lastRefundDate);
        result.setPlatformManagementYearFeeRate(platformManagerFeeYear);
        result.setPlatformManagementDayFeeRate(platformManagerRateDay);
        result.setGuaranteeServiceYearFeeRate(guaranteeRateYear);
        result.setGuaranteeServiceDayFeeRate(guaranteeRateDay);
        // 丙
        SimpleOrgInfo guarantee = organizationDubboService.getByOrgId(project.getGuaranteeCompanyOrgId());

        result.getCPart().setEmail(guarantee.getEmail());
        result.getCPart().setName(guarantee.getOrganizationName());
        result.getCPart().setInstitutionalReditCode(privacyMasks.maskInstitutionalReditCode(StringUtils.isBlank(guarantee.getUnifiedSocialCreditCode()) ? guarantee.getCharterCode() : guarantee.getUnifiedSocialCreditCode()));// 脱敏

        // 丁
        result.getDPart().setName("深圳市你我金融信息服务有限公司");
        result.getDPart().setAddress("广东省深圳市南山区科技园北区乌石头路8号天明科技大厦主楼11楼、12楼1202室");

        List<ProjectInvestOrder> projectInvestOrders = projectInvestOrderMapperExt.selectInvestedList(projectId);
        for (ProjectInvestOrder projectInvestOrder : projectInvestOrders) {
            OrgLoanContractResponseDTO.APart aPart = new OrgLoanContractResponseDTO.APart();
            if (userId.equals(projectInvestOrder.getUserId())) {
                aPart.setName(projectInvestOrder.getInvestorName());
                aPart.setIdCard(StringUtils.isBlank(projectInvestOrder.getInvestorIdCard()) ? null : projectInvestOrder.getInvestorIdCard().length() > 18 ?
                        privacyMasks.decryptPrivacy(projectInvestOrder.getInvestorIdCard()) : projectInvestOrder.getInvestorIdCard());// 解密
            } else {
                aPart.setName(projectInvestOrder.getInvestorName().substring(0, 1)
                        + projectInvestOrder.getInvestorName().replaceAll(".", "*").substring(1));// 打码
                aPart.setIdCard(StringUtils.isBlank(projectInvestOrder.getInvestorIdCard()) ? null : projectInvestOrder.getInvestorIdCard().length() > 18 ?
                        privacyMasks.maskIdCardSixTwo(privacyMasks.decryptPrivacy(projectInvestOrder.getInvestorIdCard())) : privacyMasks.maskIdCardSixTwo(projectInvestOrder.getInvestorIdCard()));// 解密脱敏
            }
            aPart.setAmount(projectInvestOrder.getAmount());
            result.getAPartList().add(aPart);
        }
        if (Byte.valueOf("1").equals(contractRequestDTO.getAddInvestor())) {
            OrgLoanContractResponseDTO.APart aPart = new OrgLoanContractResponseDTO.APart();
            UserIdentityInfoResponseDTO userIdentityInfoResponseDTO = userIdentityDubboService.get(userId);
            if (null != userIdentityInfoResponseDTO) {
                aPart.setName(userIdentityInfoResponseDTO.getName());
                aPart.setIdCard(StringUtils.isBlank(userIdentityInfoResponseDTO.getIdCard()) ? null : userIdentityInfoResponseDTO.getIdCard());
            }
            aPart.setAmount(contractRequestDTO.getAddAmount());

            result.getAPartList().add(aPart);
        }
        SimpleOrgInfo simpleOrgInfo = organizationDubboService.getByOrgId(project.getBorrowUserId());


        //与产品张光远 确认 电子邮箱  使用 官方电子邮箱
        //联系人    使用   法人姓名    身份证号码  使用  法人身份证件
        //地址       使用  使用公司 所在省+市+详细地址     联系方式   使用  法人手机号码
        // 乙方
        result.getBPart().setAddress(simpleOrgInfo.getAddress());
        result.getBPart().setEmail(simpleOrgInfo.getEmail());
        if (Objects.nonNull(simpleOrgInfo.getRepresentative()) && simpleOrgInfo.getRepresentative().length() > 2) {
            result.getBPart().setRepresentative(simpleOrgInfo.getRepresentative().substring(0, 1)
                    + simpleOrgInfo.getRepresentative().replaceAll(".", "*").substring(1));
        } else {
            result.getBPart().setRepresentative(simpleOrgInfo.getRepresentative());
        }
        result.getBPart().setName(project.getBorrowUserName());
        result.getBPart().setIdCard(StringUtils.isBlank(simpleOrgInfo.getLegalPersonCertNumber()) ? null : privacyMasks.maskIdCardSixTwo(privacyMasks.decryptPrivacy(simpleOrgInfo.getLegalPersonCertNumber())));// 解密脱敏
        result.getBPart().setInstitutionalReditCode(simpleOrgInfo.getInstitutionalReditCode());
        String mobile = simpleOrgInfo.getLegalPersonPhoneNumber();
        try {
            mobile = privacyMasks.decryptPrivacy(mobile);
            result.getBPart().setPhone(privacyMasks.maskMobile(mobile));
        } catch (Exception e) {
            result.getBPart().setPhone(mobile);
            log.warn("法人联系电话解密失败");
        }
        return result;
    }

    @Override
    public OrgCompanyFastLoanContractResponseDTO getOrgCompanyFastLoanContract(ContractRequestDTO contractRequestDTO, String userId) {
        Long projectId = contractRequestDTO.getProjectId();
        OrgCompanyFastLoanContractResponseDTO result = new OrgCompanyFastLoanContractResponseDTO();
        Project project = projectMapperExt.selectByUserIdAndProjectId(contractRequestDTO.getBorrowerUserId(), projectId);
        // 合同
        result.setContractNo("b_" + projectId);
        result.setAmount(project.getContractAmount());
        result.setDeadline(project.getDeadline());
        result.setDeadlineUnit(project.getDeadlineUnit());
        result.setBorrowRate(project.getBorrowRate().multiply(new BigDecimal(AmountHandleConstant.HUNDRED))
                .setScale(AmountHandleConstant.CALCULATE_PRECISION_TWO, BigDecimal.ROUND_HALF_EVEN));
        result.setPenaltyRate(project.getPenaltyRate().multiply(new BigDecimal(AmountHandleConstant.HUNDRED))
                .setScale(AmountHandleConstant.CALCULATE_PRECISION_TWO, BigDecimal.ROUND_HALF_EVEN));
        BigDecimal loanInterest = BigDecimal.ZERO;
        List<RepaymentPlanDTO> repaymentPlan = RepaymentPlanContext.getRepaymentPlan(RepaymentTypeEnum.enumOf(project.getRepaymentType()), project.getType(), project.getContractAmount(),
                project.getBorrowRate(), project.getDeadline(), PeriodUnitEnum.enumOf(project.getDeadlineUnit()), new Date());
        for (RepaymentPlanDTO repaymentPlanDTO : repaymentPlan) {
            loanInterest = loanInterest.add(repaymentPlanDTO.getInterest());
        }
        result.setLoanInterest(loanInterest);

        result.setRepaymentType(RepaymentTypeEnum.enumOf(project.getRepaymentType()).getDesc());
        result.setProjectTitle(project.getTitle().replaceAll("借款用途：","").replaceAll("借款用于",""));


        // 平台管理费
        BigDecimal beforeManageFee = project.getBeforeManageFee() == null ? BigDecimal.ZERO : project.getBeforeManageFee();
        BigDecimal platformManageFeeTotal = project.getManageFee().add(beforeManageFee);
        result.setPlatformManagementFee(platformManageFeeTotal);
        result.setManageFee(project.getManageFee());
        result.setBeforeManageFee(beforeManageFee);
        // 担保服务费
        BigDecimal guaranteeServiceFee = project.getContractAmount().multiply(project.getGuaranteeRate())
                .setScale(AmountHandleConstant.CALCULATE_PRECISION_TWO, BigDecimal.ROUND_HALF_EVEN);
        result.setGuaranteeServiceFee(guaranteeServiceFee);
        result.setEffectiveTime(project.getFullSuccessTime());
        result.setGuaranteeFeeChargeNode(project.getGuaranteeFeeChargeNode());
        BigDecimal platformManagerFeeYear = BigDecimal.ZERO;
        BigDecimal guaranteeRateYear = BigDecimal.ZERO;
        //↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓咨询服务费↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
        // 立即支付咨询服务费
        BigDecimal immediatePaymentConsultantFee = project.getBeforeSeekAdviceServiceFee();
        // 咨询服务费第一年应收
        BigDecimal firstYearConsultantFee = BigDecimal.ZERO;
        // 咨询服务费第二年应收
        BigDecimal secondYearsConsultantFee = BigDecimal.ZERO;
        // 咨询服务费第三年应收
        BigDecimal thirdYearConsultantFee = BigDecimal.ZERO;
        //咨询服务费
        BigDecimal consultantFee = project.getBeforeSeekAdviceServiceFee().add(project.getConsultingFee());
        result.setConsultantFee(consultantFee);
        if (ProjectFeeChargeNodeEnum.AfterSeekAdviceServiceFeeChargeNode.COLLECTION_OF_MONEY.getValue().equals(project.getAfterSeekAdviceServiceFeeChargeNode())) {
            immediatePaymentConsultantFee = consultantFee;
        } else {
            List<ProjectRate> projectRateList = projectRateMapperExt
                    .queryProjectRateListOrderByCurrentPeriodAscByProjectIdAndBorrowUserId(project.getProjectId(),
                            project.getBorrowUserId());
            for (ProjectRate projectRate : projectRateList) {
                int currentPeriod = projectRate.getCurrentPeriod();
                BigDecimal afterRate = projectRate.getAfterSeekAdviceServiceFeeRate();
                if (1 <= currentPeriod && currentPeriod <= 12) {
                    firstYearConsultantFee = project.getContractAmount().multiply(afterRate)
                            .setScale(AmountHandleConstant.CALCULATE_PRECISION_TWO, BigDecimal.ROUND_HALF_EVEN).add(firstYearConsultantFee);
                } else if (13 <= currentPeriod && currentPeriod <= 24) {
                    secondYearsConsultantFee = project.getContractAmount().multiply(afterRate)
                            .setScale(AmountHandleConstant.CALCULATE_PRECISION_TWO, BigDecimal.ROUND_HALF_EVEN).add(secondYearsConsultantFee);
                } else if (25 <= currentPeriod && currentPeriod <= 36) {
                    thirdYearConsultantFee = project.getContractAmount().multiply(afterRate)
                            .setScale(AmountHandleConstant.CALCULATE_PRECISION_TWO, BigDecimal.ROUND_HALF_EVEN).add(thirdYearConsultantFee);
                }
            }
        }
        result.setFirstYearConsultantFee(firstYearConsultantFee);
        result.setSecondYearsConsultantFee(secondYearsConsultantFee);
        result.setThirdYearConsultantFee(thirdYearConsultantFee);
        result.setImmediatePaymentConsultantFee(immediatePaymentConsultantFee);
        //↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑咨询服务费↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑

        PeriodUnitEnum periodUnitEnum = PeriodUnitEnum.enumOf(project.getDeadlineUnit());
        Date lastRefundDate = null;
        Date start = project.getFullSuccessTime() == null ? new Date() : project.getFullSuccessTime();
        BigDecimal beforeManageRate = project.getBeforeManageRate() == null ? BigDecimal.ZERO : project.getBeforeManageRate();
        switch (periodUnitEnum) {
            case MONTH:
                lastRefundDate = DateUtils.addDays(DateUtils.addMonths(start, project.getDeadline()), -1);
                platformManagerFeeYear = project.getManageRate().add(beforeManageRate).multiply(new BigDecimal(AmountHandleConstant.HUNDRED)).divide(BigDecimal.valueOf(project.getDeadline()),
                        MathContext.DECIMAL128).multiply(new BigDecimal(AmountHandleConstant.YEAR_OF_MONTH)).setScale(AmountHandleConstant.CALCULATE_PRECISION_TWO, BigDecimal.ROUND_HALF_EVEN);
                guaranteeRateYear = project.getGuaranteeRate().multiply(new BigDecimal(AmountHandleConstant.HUNDRED)).divide(BigDecimal.valueOf(project.getDeadline()),
                        MathContext.DECIMAL128).multiply(new BigDecimal(AmountHandleConstant.YEAR_OF_MONTH)).setScale(AmountHandleConstant.CALCULATE_PRECISION_TWO, BigDecimal.ROUND_HALF_EVEN);
//			consultantFeeYear = project.getConsultingRate().multiply(new BigDecimal(AmountHandleConstant.HUNDRED)).divide(BigDecimal.valueOf(project.getDeadline()),
//					MathContext.DECIMAL128).multiply(new BigDecimal(AmountHandleConstant.YEAR_OF_MONTH)).setScale(AmountHandleConstant.CALCULATE_PRECISION_TWO, BigDecimal.ROUND_HALF_EVEN);
                break;

            case DAY:
                lastRefundDate = DateUtils.addDays(start, project.getDeadline());
                platformManagerFeeYear = project.getManageRate().add(beforeManageRate).multiply(new BigDecimal(AmountHandleConstant.HUNDRED)).divide(BigDecimal.valueOf(project.getDeadline()),
                        MathContext.DECIMAL128).multiply(new BigDecimal(AmountHandleConstant.YEAR_OF_DAY)).setScale(AmountHandleConstant.CALCULATE_PRECISION_TWO, BigDecimal.ROUND_HALF_EVEN);
                guaranteeRateYear = project.getGuaranteeRate().multiply(new BigDecimal(AmountHandleConstant.HUNDRED)).divide(BigDecimal.valueOf(project.getDeadline()),
                        MathContext.DECIMAL128).multiply(new BigDecimal(AmountHandleConstant.YEAR_OF_DAY)).setScale(AmountHandleConstant.CALCULATE_PRECISION_TWO, BigDecimal.ROUND_HALF_EVEN);
//			consultantFeeYear = project.getConsultingRate().multiply(new BigDecimal(AmountHandleConstant.HUNDRED)).divide(BigDecimal.valueOf(project.getDeadline()),
//					MathContext.DECIMAL128).multiply(new BigDecimal(AmountHandleConstant.YEAR_OF_DAY)).setScale(AmountHandleConstant.CALCULATE_PRECISION_TWO, BigDecimal.ROUND_HALF_EVEN);
                break;
            default:
                break;
        }
        result.setRefundDate(lastRefundDate);
        result.setPlatformManagementFeeRateYear(platformManagerFeeYear);
        result.setGuaranteeServiceFeeRateYear(guaranteeRateYear);

        // 丙
        SimpleOrgInfo guarantee = organizationDubboService.getByOrgId(project.getGuaranteeCompanyOrgId());

        result.getCPart().setEmail(guarantee.getEmail());
        result.getCPart().setName(guarantee.getOrganizationName());
        String cCode = StringUtils.isBlank(guarantee.getUnifiedSocialCreditCode()) ? guarantee.getCharterCode() : guarantee.getUnifiedSocialCreditCode();
        result.getCPart().setInstitutionalReditCode(privacyMasks.maskInstitutionalReditCode(cCode));// 脱敏

        // 丁
        result.getDPart().setName("深圳市你我金融信息服务有限公司");
        result.getDPart().setAddress("广东省深圳市南山区科技园北区乌石头路8号天明科技大厦主楼11楼、12楼1202室");

        List<InvestorContractDTO> investorContractDTOs = contractBaseService.getInvestUserInfoFromInvestorOrder(projectId);
        for (InvestorContractDTO investorContractDTO : investorContractDTOs) {
            OrgCompanyFastLoanContractResponseDTO.APart aPart = new OrgCompanyFastLoanContractResponseDTO.APart();
            if (userId.equals(investorContractDTO.getInvestUserId())) {
                aPart.setName(investorContractDTO.getInvestUserName());
                aPart.setIdCard(contractBaseService.maskCodeNoMask(investorContractDTO.getInvestorIdCard(), investorContractDTO.getInvestorType() == 2));// 解密
            } else {
                aPart.setName(contractBaseService.maskName(investorContractDTO.getInvestUserName()));// 打码
                aPart.setIdCard(contractBaseService.maskCode(investorContractDTO.getInvestorIdCard(), investorContractDTO.getInvestorType() == 2));// 解密脱敏
            }
            aPart.setAmount(investorContractDTO.getInvestAmount());
            result.getAPartList().add(aPart);
        }
        if (Byte.valueOf("1").equals(contractRequestDTO.getAddInvestor())) {
            OrgCompanyFastLoanContractResponseDTO.APart aPart = new OrgCompanyFastLoanContractResponseDTO.APart();
            InvestorContractDTO investorContractDTO = contractBaseService.getCurrentUserContractDTO(userId);
            if (null != investorContractDTO) {
                aPart.setName(investorContractDTO.getInvestUserName());
                aPart.setIdCard(StringUtils.isBlank(investorContractDTO.getInvestorIdCard()) ? null : investorContractDTO.getInvestorIdCard());
            }
            aPart.setAmount(contractRequestDTO.getAddAmount());

            result.getAPartList().add(aPart);
        }

        //乙方
        SimpleOrgInfo borrowOrg = organizationDubboService.getByOrgId(project.getBorrowUserId());
        result.getBPart().setName(borrowOrg.getOrganizationName());
        String bCode = StringUtils.isBlank(borrowOrg.getUnifiedSocialCreditCode()) ? borrowOrg.getCharterCode() : borrowOrg.getUnifiedSocialCreditCode();
        result.getBPart().setInstitutionalReditCode(privacyMasks.maskInstitutionalReditCode(bCode));
        result.getBPart().setEmail(borrowOrg.getEmail());
        result.getBPart().setRepresentative(borrowOrg.getRepresentative());
        result.getBPart().setIdCard(StringUtils.isNoneBlank(borrowOrg.getLegalPersonCertNumber()) ? privacyMasks.maskIdCard(privacyMasks.decryptPrivacy(borrowOrg.getLegalPersonCertNumber())) : "");
        result.getBPart().setPhone(StringUtils.isNoneBlank(borrowOrg.getLegalPersonPhoneNumber()) ? privacyMasks.decryptPrivacy(borrowOrg.getLegalPersonPhoneNumber()) : "");
        result.getBPart().setAddress(StringUtils.isBlank(borrowOrg.getAddress()) ? project.getLoanProvince().concat(project.getLoanCity()).concat(project.getLoanArea()) : borrowOrg.getAddress());
        //戊方
        AccountCompanyDTO accountCompanyByBusinessLicense = accountCompanyDubboService.getAccountCompanyByBusinessLicense(project.getConsultingBusinessLicense());
        SimpleOrgInfo informationConsultantOrg = organizationDubboService.getByOrgId(accountCompanyByBusinessLicense.getUserId());
        result.getEPart().setName(informationConsultantOrg.getOrganizationName());
        String eCode = StringUtils.isBlank(informationConsultantOrg.getUnifiedSocialCreditCode()) ? informationConsultantOrg.getCharterCode() : informationConsultantOrg.getUnifiedSocialCreditCode();
        result.getEPart().setInstitutionalReditCode(privacyMasks.maskInstitutionalReditCode(eCode));// 脱敏
        result.getEPart().setAddress(informationConsultantOrg.getAddress());

//	    result.setConsultantFeeYear(consultantFeeYear);
        BigDecimal payTotal = loanInterest.add(platformManageFeeTotal).add(guaranteeServiceFee).add(consultantFee);
        result.setPayTotal(payTotal);
        // 借款人综合资金成本费率计算公式为：（利息 +平台管理费 +担保服务费） /借款金额 /借款期限 *12
        BigDecimal payTotalRateYear = payTotal.divide(project.getContractAmount(), MathContext.DECIMAL128)
                .divide(BigDecimal.valueOf(project.getDeadline()), MathContext.DECIMAL128)
                .multiply(
                        new BigDecimal((PeriodUnitEnum.MONTH.equals(periodUnitEnum) ? AmountHandleConstant.YEAR_OF_MONTH
                                : AmountHandleConstant.YEAR_OF_DAY)))
                .multiply(new BigDecimal(AmountHandleConstant.HUNDRED))
                .setScale(AmountHandleConstant.CALCULATE_PRECISION_TWO, BigDecimal.ROUND_HALF_EVEN);
        result.setPayTotal(payTotal);
        result.setPayTotalRateYear(payTotalRateYear);
        return result;
    }

    @Override
    public OrgPersonalFastLoanContractResponseDTO getOrgPersonalFastLoanContractResponseDTO(ContractRequestDTO contractRequestDTO, String userId) {
        Long projectId = contractRequestDTO.getProjectId();
        OrgPersonalFastLoanContractResponseDTO result = new OrgPersonalFastLoanContractResponseDTO();
        Project project = projectMapperExt.selectByUserIdAndProjectId(contractRequestDTO.getBorrowerUserId(), projectId);
        // 合同
        result.setContractNo("b_" + projectId);
        result.setAmount(project.getContractAmount());
        result.setDeadline(project.getDeadline());
        result.setDeadlineUnit(project.getDeadlineUnit());
        result.setBorrowRate(project.getBorrowRate().multiply(new BigDecimal(AmountHandleConstant.HUNDRED))
                .setScale(AmountHandleConstant.CALCULATE_PRECISION_TWO, BigDecimal.ROUND_HALF_EVEN));
        result.setPenaltyRate(project.getPenaltyRate().multiply(new BigDecimal(AmountHandleConstant.HUNDRED))
                .setScale(AmountHandleConstant.CALCULATE_PRECISION_TWO, BigDecimal.ROUND_HALF_EVEN));
        BigDecimal loanInterest = BigDecimal.ZERO;
        List<RepaymentPlanDTO> repaymentPlan = RepaymentPlanContext.getRepaymentPlan(RepaymentTypeEnum.enumOf(project.getRepaymentType()), project.getType(), project.getContractAmount(),
                project.getBorrowRate(), project.getDeadline(), PeriodUnitEnum.enumOf(project.getDeadlineUnit()), new Date());
        for (RepaymentPlanDTO repaymentPlanDTO : repaymentPlan) {
            loanInterest = loanInterest.add(repaymentPlanDTO.getInterest());
        }
        result.setLoanInterest(loanInterest);

        result.setRepaymentType(RepaymentTypeEnum.enumOf(project.getRepaymentType()).getDesc());
        result.setProjectTitle(project.getTitle().replaceAll("借款用途：","").replaceAll("借款用于",""));

        // 平台管理费
        BigDecimal beforeManageFee = project.getBeforeManageFee() == null ? BigDecimal.ZERO : project.getBeforeManageFee();
        BigDecimal platformManageFeeTotal = beforeManageFee.add(project.getManageFee());
        result.setPlatformManagementFee(platformManageFeeTotal);
        result.setManageFee(project.getManageFee());
        result.setBeforeManageFee(beforeManageFee);
        // 担保服务费
        BigDecimal guaranteeServiceFee = project.getContractAmount().multiply(project.getGuaranteeRate())
                .setScale(AmountHandleConstant.CALCULATE_PRECISION_TWO, BigDecimal.ROUND_HALF_EVEN);
        result.setGuaranteeServiceFee(guaranteeServiceFee);
        result.setEffectiveTime(project.getFullSuccessTime());
        result.setGuaranteeFeeChargeNode(project.getGuaranteeFeeChargeNode());
        BigDecimal platformManagerFeeYear = BigDecimal.ZERO;
        BigDecimal guaranteeRateYear = BigDecimal.ZERO;
        // ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓咨询服务费↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
        // 立即支付咨询服务费
        BigDecimal immediatePaymentConsultantFee = project.getBeforeSeekAdviceServiceFee();
        // 咨询服务费第一年应收
        BigDecimal firstYearConsultantFee = BigDecimal.ZERO;
        // 咨询服务费第二年应收
        BigDecimal secondYearsConsultantFee = BigDecimal.ZERO;
        // 咨询服务费第三年应收
        BigDecimal thirdYearConsultantFee = BigDecimal.ZERO;
        // 咨询服务费
        BigDecimal consultantFee = project.getBeforeSeekAdviceServiceFee().add(project.getConsultingFee());
        result.setConsultantFee(consultantFee);
        if (ProjectFeeChargeNodeEnum.AfterSeekAdviceServiceFeeChargeNode.COLLECTION_OF_MONEY.getValue().equals(project.getAfterSeekAdviceServiceFeeChargeNode())) {
            immediatePaymentConsultantFee = consultantFee;
        } else {
            List<ProjectRate> projectRateList = projectRateMapperExt
                    .queryProjectRateListOrderByCurrentPeriodAscByProjectIdAndBorrowUserId(project.getProjectId(),
                            project.getBorrowUserId());
            for (ProjectRate projectRate : projectRateList) {
                int currentPeriod = projectRate.getCurrentPeriod();
                BigDecimal afterRate = projectRate.getAfterSeekAdviceServiceFeeRate();
                if (1 <= currentPeriod && currentPeriod <= 12) {
                    firstYearConsultantFee = project.getContractAmount().multiply(afterRate)
                            .setScale(AmountHandleConstant.CALCULATE_PRECISION_TWO, BigDecimal.ROUND_HALF_EVEN)
                            .add(firstYearConsultantFee);
                } else if (13 <= currentPeriod && currentPeriod <= 24) {
                    secondYearsConsultantFee = project.getContractAmount().multiply(afterRate)
                            .setScale(AmountHandleConstant.CALCULATE_PRECISION_TWO, BigDecimal.ROUND_HALF_EVEN)
                            .add(secondYearsConsultantFee);
                } else if (25 <= currentPeriod && currentPeriod <= 36) {
                    thirdYearConsultantFee = project.getContractAmount().multiply(afterRate)
                            .setScale(AmountHandleConstant.CALCULATE_PRECISION_TWO, BigDecimal.ROUND_HALF_EVEN)
                            .add(thirdYearConsultantFee);
                }
            }
        }
        result.setFirstYearConsultantFee(firstYearConsultantFee);
        result.setSecondYearsConsultantFee(secondYearsConsultantFee);
        result.setThirdYearConsultantFee(thirdYearConsultantFee);
        result.setImmediatePaymentConsultantFee(immediatePaymentConsultantFee);
        // ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑咨询服务费↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
        Date lastRefundDate = null;
        PeriodUnitEnum periodUnitEnum = PeriodUnitEnum.enumOf(project.getDeadlineUnit());
        BigDecimal beforeManageRate = project.getBeforeManageRate() == null ? BigDecimal.ZERO : project.getBeforeManageRate();
        switch (periodUnitEnum) {
            case MONTH:
                lastRefundDate = DateUtils.addDays(DateUtils.addMonths(new Date(), project.getDeadline()), -1);
                platformManagerFeeYear = project.getManageRate().add(beforeManageRate).multiply(new BigDecimal(AmountHandleConstant.HUNDRED)).divide(BigDecimal.valueOf(project.getDeadline()),
                        MathContext.DECIMAL128).multiply(new BigDecimal(AmountHandleConstant.YEAR_OF_MONTH)).setScale(AmountHandleConstant.CALCULATE_PRECISION_TWO, BigDecimal.ROUND_HALF_EVEN);
                guaranteeRateYear = project.getGuaranteeRate().multiply(new BigDecimal(AmountHandleConstant.HUNDRED)).divide(BigDecimal.valueOf(project.getDeadline()),
                        MathContext.DECIMAL128).multiply(new BigDecimal(AmountHandleConstant.YEAR_OF_MONTH)).setScale(AmountHandleConstant.CALCULATE_PRECISION_TWO, BigDecimal.ROUND_HALF_EVEN);
//			consultantFeeYear = project.getConsultingRate().multiply(new BigDecimal(AmountHandleConstant.HUNDRED)).divide(BigDecimal.valueOf(project.getDeadline()),
//					MathContext.DECIMAL128).multiply(new BigDecimal(AmountHandleConstant.YEAR_OF_MONTH)).setScale(AmountHandleConstant.CALCULATE_PRECISION_TWO, BigDecimal.ROUND_HALF_EVEN);
                break;

            case DAY:
                lastRefundDate = DateUtils.addDays(new Date(), project.getDeadline());
                platformManagerFeeYear = project.getManageRate().add(beforeManageRate).multiply(new BigDecimal(AmountHandleConstant.HUNDRED)).divide(BigDecimal.valueOf(project.getDeadline()),
                        MathContext.DECIMAL128).multiply(new BigDecimal(AmountHandleConstant.YEAR_OF_DAY)).setScale(AmountHandleConstant.CALCULATE_PRECISION_TWO, BigDecimal.ROUND_HALF_EVEN);
                guaranteeRateYear = project.getGuaranteeRate().multiply(new BigDecimal(AmountHandleConstant.HUNDRED)).divide(BigDecimal.valueOf(project.getDeadline()),
                        MathContext.DECIMAL128).multiply(new BigDecimal(AmountHandleConstant.YEAR_OF_DAY)).setScale(AmountHandleConstant.CALCULATE_PRECISION_TWO, BigDecimal.ROUND_HALF_EVEN);
//			consultantFeeYear = project.getConsultingRate().multiply(new BigDecimal(AmountHandleConstant.HUNDRED)).divide(BigDecimal.valueOf(project.getDeadline()),
//					MathContext.DECIMAL128).multiply(new BigDecimal(AmountHandleConstant.YEAR_OF_DAY)).setScale(AmountHandleConstant.CALCULATE_PRECISION_TWO, BigDecimal.ROUND_HALF_EVEN);
                break;
            default:
                break;
        }
        result.setRefundDate(lastRefundDate);
        result.setPlatformManagementFeeRateYear(platformManagerFeeYear);
        result.setGuaranteeServiceFeeRateYear(guaranteeRateYear);

        // 丙
        SimpleOrgInfo guarantee = organizationDubboService.getByOrgId(project.getGuaranteeCompanyOrgId());
        String cCode = StringUtils.isBlank(guarantee.getUnifiedSocialCreditCode()) ? guarantee.getCharterCode() : guarantee.getUnifiedSocialCreditCode();
        result.getCPart().setEmail(guarantee.getEmail());
        result.getCPart().setName(guarantee.getOrganizationName());
        result.getCPart().setInstitutionalReditCode(privacyMasks.maskInstitutionalReditCode(cCode));// 脱敏

        // 丁
        result.getDPart().setName("深圳市你我金融信息服务有限公司");
        result.getDPart().setAddress("广东省深圳市南山区科技园北区乌石头路8号天明科技大厦主楼11楼、12楼1202室");

        List<InvestorContractDTO> investorContractDTOs = contractBaseService.getInvestUserInfoFromInvestorOrder(projectId);
        for (InvestorContractDTO investorContractDTO : investorContractDTOs) {
            OrgPersonalFastLoanContractResponseDTO.APart aPart = new OrgPersonalFastLoanContractResponseDTO.APart();
            if (userId.equals(investorContractDTO.getInvestUserId())) {
                aPart.setName(investorContractDTO.getInvestUserName());
                aPart.setIdCard(contractBaseService.maskCodeNoMask(investorContractDTO.getInvestorIdCard(), investorContractDTO.getInvestorType() == 2));// 解密
            } else {
                aPart.setName(contractBaseService.maskName(investorContractDTO.getInvestUserName()));// 打码
                aPart.setIdCard(contractBaseService.maskCode(investorContractDTO.getInvestorIdCard(), investorContractDTO.getInvestorType() == 2));// 解密脱敏
            }
            aPart.setAmount(investorContractDTO.getInvestAmount());
            result.getAPartList().add(aPart);
        }
        if (Byte.valueOf("1").equals(contractRequestDTO.getAddInvestor())) {
            OrgPersonalFastLoanContractResponseDTO.APart aPart = new OrgPersonalFastLoanContractResponseDTO.APart();
            InvestorContractDTO investorContractDTO = contractBaseService.getCurrentUserContractDTO(userId);
            if (null != investorContractDTO) {
                aPart.setName(investorContractDTO.getInvestUserName());
                aPart.setIdCard(StringUtils.isBlank(investorContractDTO.getInvestorIdCard()) ? null : investorContractDTO.getInvestorIdCard());
            }
            aPart.setAmount(contractRequestDTO.getAddAmount());

            result.getAPartList().add(aPart);
        }

        //乙方
        UserIdentityInfoResponseDTO borrower = userIdentityDubboService
                .get(project.getBorrowUserId());
        result.getBPart().setAddress((StringUtils.isBlank(borrower.getAddress())) ? project.getLoanProvince().concat(project.getLoanCity()).concat(project.getLoanArea()) : borrower.getAddress());
        result.getBPart().setName(project.getBorrowUserName().substring(0, 1)
                + project.getBorrowUserName().replaceAll(".", "*").substring(1));
        result.getBPart().setIdCard(privacyMasks.maskIdCardSixTwo(borrower.getIdCard()));// 解密脱敏
        //戊方
        AccountCompanyDTO accountCompanyByBusinessLicense = accountCompanyDubboService.getAccountCompanyByBusinessLicense(project.getConsultingBusinessLicense());
        SimpleOrgInfo informationConsultantOrg = organizationDubboService.getByOrgId(accountCompanyByBusinessLicense.getUserId());
        String eCode = StringUtils.isBlank(informationConsultantOrg.getUnifiedSocialCreditCode()) ? informationConsultantOrg.getCharterCode() : informationConsultantOrg.getUnifiedSocialCreditCode();
        result.getEPart().setName(informationConsultantOrg.getOrganizationName());
        result.getEPart().setInstitutionalReditCode(privacyMasks.maskInstitutionalReditCode(eCode));// 脱敏
        result.getEPart().setAddress(informationConsultantOrg.getAddress());

        BigDecimal payTotal = loanInterest.add(platformManageFeeTotal).add(guaranteeServiceFee).add(consultantFee);
        // 借款人综合资金成本费率计算公式为：（利息 +平台管理费 +担保服务费） /借款金额 /借款期限 *12
        BigDecimal payTotalRateYear = payTotal.divide(project.getContractAmount(), MathContext.DECIMAL128)
                .divide(BigDecimal.valueOf(project.getDeadline()), MathContext.DECIMAL128)
                .multiply(
                        new BigDecimal((PeriodUnitEnum.MONTH.equals(periodUnitEnum) ? AmountHandleConstant.YEAR_OF_MONTH
                                : AmountHandleConstant.YEAR_OF_DAY)))
                .multiply(new BigDecimal(AmountHandleConstant.HUNDRED))
                .setScale(AmountHandleConstant.CALCULATE_PRECISION_TWO, BigDecimal.ROUND_HALF_EVEN);
        result.setPayTotal(payTotal);
        result.setPayTotalRateYear(payTotalRateYear);
        return result;
    }


    @Override
    public CreditorTransferProtocolPreviewResponseDTO creditorTransferProtocolPreview(Long creditorSaleId, String transferUserId, String userId) {
        Assert.notNull(creditorSaleId, "creditorSaleId is not null");
        Assert.notNull(creditorSaleId, "transferUserId is not null");
        Assert.notNull(userId, "investorUserId is not null");
        return investService.creditorTransferProtocolPreview(creditorSaleId, transferUserId, userId);
    }

    @Override
    public SaleCreditorTransferProtocolPreviewResponseDTO saleCreditorTransferProtocolPreview(Long investOrderId, BigDecimal saleAmount) {
        Assert.notNull(investOrderId, "investOrderId is not null");
        Assert.notNull(saleAmount, "saleAmount is not null");
        return investService.saleCreditorTransferProtocolPreview(investOrderId, saleAmount);
    }

    @Override
    public List<UserInvestDueInGroupDTO> getUserInvestDueInGroupByUserId(List<String> userIdList) {
        List<UserInvestDueInGroupDTO> userInvestDueInGroupDTOList = new ArrayList<UserInvestDueInGroupDTO>();
        List<UserInvestDueInDTO> plans = projectInvestorPlanMapperExt.selectUserInvestDueInGroupByUserIds(userIdList);
        plans.forEach(biz -> {
            UserInvestDueInGroupDTO userInvestDueInGroupDTO = new UserInvestDueInGroupDTO();
            userInvestDueInGroupDTO.setUserId(biz.getUserId());
            BigDecimal dueInPrincipal = biz.getCapital().subtract(biz.getReceivedCapital());
            userInvestDueInGroupDTO.setDueInPrincipal(dueInPrincipal);
            BigDecimal expectedEarning = biz.getInterest().subtract(biz.getReceivedInterest());
            userInvestDueInGroupDTO.setExpectedEarning(expectedEarning);
            userInvestDueInGroupDTOList.add(userInvestDueInGroupDTO);
        });
        return userInvestDueInGroupDTOList;
    }

    @Override
    public FastloanInvestSuccessDTO getFastloanInvestSuccessDTO(String userId) {
        InvestFlowConfig investFlowConfig = flowConfigLocalService.queryByType(InvestFlowConfigTypeEnum.SPEEDLOAN_INVEST_SUCCEED);
        if (null == investFlowConfig) {
            return null;
        }
        if (Byte.valueOf("1").equals(investFlowConfig.getPageType()) && Byte.valueOf("1").equals(investFlowConfig.getIsShow())) {
            UserInvestConfig config = autoBatchInvestService.queryUserInvestConfig(userId, InvestWayEnum.AUTO);
            if (null != config && Byte.valueOf("1").equals(config.getEnableAuto())) {
                investFlowConfig.setIsShow(Byte.valueOf("0"));// 不显示
            }
        }
        FastloanInvestSuccessDTO fastloanInvestSuccessDTO = new FastloanInvestSuccessDTO();
        fastloanInvestSuccessDTO.setButtonText(investFlowConfig.getButtonText());
        fastloanInvestSuccessDTO.setContent(investFlowConfig.getContent());
        fastloanInvestSuccessDTO.setIsShow(investFlowConfig.getIsShow());
        fastloanInvestSuccessDTO.setLink(investFlowConfig.getLink());
        fastloanInvestSuccessDTO.setPageType(investFlowConfig.getPageType());
        fastloanInvestSuccessDTO.setTitle(investFlowConfig.getTitle());
        return fastloanInvestSuccessDTO;
    }

    @Override
    public Integer getInvestingCount(String userId) {
        return projectInvestOrderMapperExt.selectInvestingCountByUserId(userId);
    }

    @Override
    public void vaildSurplusCanInvestAmount(String userId, BigDecimal investAmout) {
    	investCommonServer.vaildSurplusCanInvestAmount(userId,investAmout);
    }

    @Override
    public void cancelInvestOrder(String userId, Long investOrderId) {
        ProjectInvestOrder investOrder = investService.queryInvestOrder(investOrderId);
        checkGatewayInvestOrder(userId, investOrder);
        //该订单为手动网关，处理中，未超时。调用account查询存管
        CompleteInvestOrderResponseDTO responseDTO = accountInvestDubboService.completeInvestOrderIfExist(investOrder.getAccountId(), investOrderId);
        if (!responseDTO.isOrderExists()) {   //存管不存在该投资订单，直接关闭
            investService.cancelInvestOrderLocal(investOrderId, InvestOrderCloseReasonEnum.PAY_CANCELED);
        } else {
            if (responseDTO.isOrderSucceed()) {
                throw new BizException("TRD10019"); //该订单已支付成功
            } else {
                throw new BizException("TRD10020"); //存管订单失败也提示为该订单已超时失效
            }
        }
    }

    @Override
    public InvestPaymentResponseDTO payInvestOrder(String userId, Long investOrderId, String niiwooRedirectUrl) {
        ProjectInvestOrder investOrder = investService.queryInvestOrder(investOrderId);
        checkGatewayInvestOrder(userId, investOrder);
        Long accountId = investOrder.getAccountId();
        Date expired = new DateTime(new Date()).plusMinutes(10).toDate();
        InvestPayDubboRequestDTO requestDTO = new InvestPayDubboRequestDTO();
        requestDTO.setUserId(userId);
        requestDTO.setProjectId(investOrder.getProjectId());
        requestDTO.setProjectType(investOrder.getProjectType());
        requestDTO.setProjectTitle(investOrder.getTitle());
        requestDTO.setDeadline(investOrder.getDeadline());
        requestDTO.setDeadlineUnit(investOrder.getDeadlineUnit());
        requestDTO.setInvestAmount(investOrder.getAmount());
        requestDTO.setInvestOrderId(investOrder.getId());
        requestDTO.setExpired(expired);
        requestDTO.setNiiwooRedirectUrl(niiwooRedirectUrl);
        requestDTO.setBorrowerUserId(investOrder.getBorrowUserId());
        //重置该投资订单过期时间
        investService.resetExpiredTime(investOrder.getId(), expired);
        //账户中心再次发起投资支付
        InvestPaymentRedoResponseDTO responseDTO = accountInvestDubboService.redoInvestOrderPayment(accountId, requestDTO);
        InvestPaymentResponseDTO dto = new InvestPaymentResponseDTO().setInvestOrderId(investOrderId);
        if (!responseDTO.isOrderExists()) {
            dto.setGatewayMode(responseDTO.isGateWayMode());
            dto.setGatewayDTO(responseDTO.getGatewayDTO());
        } else {
            if (responseDTO.isOrderSucceed()) {
                throw new BizException("TRD10019"); //该订单已支付成功
            } else {
                throw new BizException("TRD10020"); //存管订单失败也提示为该订单已超时失效
            }
        }
        return dto;
    }

    private void checkGatewayInvestOrder(String userId, ProjectInvestOrder investOrder) {
        //查询本地该用户、该订单，不存在抛出业务异常
        if (investOrder == null || !investOrder.getUserId().equals(userId)) {
            throw new BizException("TRD10001");
        }
        //非手动网关投资不能操作取消
        if (!InvestWayEnum.MANUAL_GATEWAY.getValue().equals(investOrder.getType())) {
            throw new BizException("TRD10018");
        }
        //订单状态不为处理中：成功、已取消抛出业务异常
        if (ProjectInvestOrderStatusEnum.SUCCESS.getValue().equals(investOrder.getStatus())) {
            throw new BizException("TRD10019"); //该订单已支付成功
        }
        if (ProjectInvestOrderStatusEnum.CANCEL.getValue().equals(investOrder.getStatus())) {
            throw new BizException("TRD10020"); //该订单已超时失效
        }
    }

    public RecommendInvestResponseDTO queryRecommendInvest() {

        return investService.queryRecommendInvest();
    }

    @Override
    public RecommendInvestResponseDTO queryNoviceRecommendInvest(String userId) {
        boolean isShowFirstNovie = true;
		IntelligenceInvestSwitchResponseDTO isOpen = intelligenceInvestService.intelligenceInvestSwitch(IntelligenceSwitchSourceEnum.NORMAL.getCode());
		if(isOpen.getIntelligenceInvestSwitch() == 1){
			if (userId != null) {
				//用户新手智能投相关信息
				NoviceIntelligenceInvestInfoResponseDTO dto = noviceIntelligenceInvestService.getNoviceBasicInfo(userId);
				//注册在Y天以内的切可投大于0，展示新手智能投* 1.展示，0 不展示
				isShowFirstNovie = dto.getDays() > 0 &&
						dto.getNoviceSurplusInvestMoney().compareTo(BigDecimal.ZERO) > 0;
			}
		} else {
			isShowFirstNovie = false;
		}
		if(isShowFirstNovie){
			return investService.queryNoviceRecommendInvest();
		}else{
            return investService.queryRecommendInvest();
		}

    }

    @Override
    public FilterInvestConfigDTO queryNormalInvestingSelector() {

        return investService.queryNormalInvestingSelector();
    }

    public String selectConfig(TradeConfigEnum tradeConfigEnum) {
        return tradeConfigLocalService.selectTradeConfigByEmun(tradeConfigEnum);
    }

    @Override
    public CreditSuccessInfoDTO getCreditSuccessInfo(Long investOrderId) {

        return investService.getCreditSuccessInfo(investOrderId);
    }

    @Override
    public DripSummaryInfoRespDTO getMyInvestSummaryInfo(String userId){
        DripSummaryInfoRespDTO dripSummaryInfoRespDTO = new DripSummaryInfoRespDTO();

        QueryMoneyTotalRequestDTO requestDTO = new QueryMoneyTotalRequestDTO();
        requestDTO.setUserId(userId);
        //累计投资金额、累计赚取收益、累计获得平台奖励金额
        QueryMoneyTotalResponseDTO queryMoneyTotalResponseDTO = moneyTotalDubboService.queryMoneyTotal(requestDTO);
        if(queryMoneyTotalResponseDTO!=null) {
            dripSummaryInfoRespDTO.setInvestTotalAmount(queryMoneyTotalResponseDTO.getInvestTotal());
            dripSummaryInfoRespDTO.setInvestIncome(queryMoneyTotalResponseDTO.getIncomeTotal());
            dripSummaryInfoRespDTO.setRewardAmount(queryMoneyTotalResponseDTO.getPlatformGiven());
        }

        //第一次投资时间、金额、用途
        ProjectInvestOrder projectInvestOrder = projectInvestOrderMapperExt.queryFirstInvestInfo(userId);
        if(projectInvestOrder!=null){
            dripSummaryInfoRespDTO.setFirstInvestTime(projectInvestOrder.getCreateTime());
            dripSummaryInfoRespDTO.setFirstInvestAmount(projectInvestOrder.getAmount());
            dripSummaryInfoRespDTO.setProjectTitle(projectInvestOrder.getTitle());
        }

        //历史累计最高投资月份和金额（需展示月份、金额）
        DripSummaryInfoRespDTO maxInvestForMonth = projectInvestOrderMapperExt.queryMaxInvestForMonth(userId);
        if(maxInvestForMonth!=null){
            dripSummaryInfoRespDTO.setInvestMaxMonth(maxInvestForMonth.getInvestMaxMonth());
            dripSummaryInfoRespDTO.setInvestMaxMonthAmount(maxInvestForMonth.getInvestMaxMonthAmount());
        }

        //历史单日最高投资金额（需展示日期、金额）
        DripSummaryInfoRespDTO maxInvestForDay = projectInvestOrderMapperExt.queryMaxInvestForDay(userId);
        if(maxInvestForDay!=null){
            dripSummaryInfoRespDTO.setInvestMaxDay(maxInvestForDay.getInvestMaxDay());
            dripSummaryInfoRespDTO.setInvestMaxDayAmount(maxInvestForDay.getInvestMaxDayAmount());
        }

        //历史当月最多满标笔数（需展示月份，个数）
        DripSummaryInfoRespDTO fullProjectInfo = projectInvestOrderMapperExt.queryMaxFullProjectForMonth(userId);
        if(fullProjectInfo!=null){
            dripSummaryInfoRespDTO.setFullMonth(fullProjectInfo.getFullMonth());
            dripSummaryInfoRespDTO.setFullCount(fullProjectInfo.getFullCount());
        }

        //历史当月压标笔数（需展示月份，个数）
        DripSummaryInfoRespDTO pressureProjectInfo = projectInvestOrderMapperExt.queryMaxPressureProjectForMonth(userId);
        if(pressureProjectInfo!=null){
            dripSummaryInfoRespDTO.setPressureMonth(pressureProjectInfo.getPressureMonth());
            dripSummaryInfoRespDTO.setPressureCount(pressureProjectInfo.getPressureCount());
        }

        //历史累计投资借款人人数（如投资 2 个借款标，都是 1 个借款人发起的，则为投资了 1 个借款人）
        DripSummaryInfoRespDTO borrowerCount = projectInvestOrderMapperExt.queryInvestBorrowerCount(userId);
        dripSummaryInfoRespDTO.setInvestCount(borrowerCount.getInvestCount());

        return dripSummaryInfoRespDTO;
    }

    @Override
    public PageResponseDTO<InvestingProjectDTO> getNoviceInvestList(NoviceInvestListRequestDTO requestDTO) {
        NewbieProjectConfig newbieProjectConfig = newbieProjectConfigMapper.selectNewbieProjectConfig(null);
        requestDTO.setChannelCode(newbieProjectConfig.getChannelCode());
        PageResponseDTO<InvestingProjectDTO> dtoPageResponseDTO = new PageResponseDTO<>();

        List<InvestingProjectDTO> result = new ArrayList<>();

        List<ProjectInvesting> list = projectInvestingMapperExt.selectNoviceInvestPage(requestDTO);
        if(CollectionUtils.isEmpty(list)){
            return dtoPageResponseDTO;
        }
        Integer count = projectInvestingMapperExt.selectNoviceInvestPageCount(requestDTO);
        //实时找到用户信息列表
        Set<String> stringList = list.stream().map(ProjectInvesting::getBorrowUserId).collect(Collectors.toSet());
        List<UserBasicInfoDTO> dtoList = userBasicInfoDubboService.queryListByUserIdSet(stringList);
        //查询加息的标
        List<InvestAddInterestRateConfig> configs = investAddInterestRateConfigMapperExt.selectAll();
        List<Long> projectIds = list.stream().map(ProjectInvesting::getProjectId).collect(Collectors.toList());
        List<Project> projectList = projectMapperExt.selectListByProjectIdSet(projectIds);
        for (ProjectInvesting projectInvesting : list) {
            for (UserBasicInfoDTO userBasicInfoDTO : dtoList) {
                if(userBasicInfoDTO.getUserId().equals(projectInvesting.getBorrowUserId())){
                    projectInvesting.setBorrowNickName(userBasicInfoDTO.getNickName());
                    projectInvesting.setBorrowHeadImage(userBasicInfoDTO.getHeadImage());
                    break;
                }
            }
            InvestingProjectDTO dto = this.convertToInvestingProjectDTO(projectInvesting);
            // 鸿特机构标的，若为“共借”借款，散标列表、标的详情页和投资订单页的授信类型不显示  (是否主借人?0.否;1.是)
            for (Project project : projectList) {
                if(project.getProjectId().equals(dto.getProjectId())){
                    dto.setIsMasterBorrower(project.getIsMasterBorrower());
                    dto.setLoanType(project.getLoanType()); //借款类型
                    result.add(dto);
                    break;
                }
            }
            //找到加息的活动
            for (InvestAddInterestRateConfig config : configs) {
                if(config.getId().equals(projectInvesting.getActivityId())){
                    dto.setInterestAddTitle(config.getTitle());
                    dto.setInterestAddRate(projectInvesting.getActivityRaiseRate().multiply(BigDecimal.valueOf(100)));
                    break;
                }
            }

            projectLocalService.resetInvestEndTime(projectInvesting.getProjectId());
        }
        //成功借款次数
        //completeLoanTimes(result);
        investService.completeLoanTimes(result);
        dtoPageResponseDTO.setItems(result);
        dtoPageResponseDTO.measureTotalPage(count,requestDTO.getPageSize());
        return dtoPageResponseDTO;
    }

    @Override
    public NoviceInvestInfoResponseDTO getNoviceInvestInfos(String userId,String channelCode) {

        return investService.getNoviceInvestInfos(userId,channelCode);
    }

    @Override
    public InvestmentRateInfoResponseDTO getInvestmentRateInfo(String userId) {
        Byte userIdentity;
        if (userId != null) {
            //用户新手智能投相关信息
            NoviceIntelligenceInvestInfoResponseDTO dto = noviceIntelligenceInvestService.getNoviceBasicInfo(userId);
            //，展示新手智能投* 1.展示，0 不展示
            userIdentity = (dto.getNoviceSurplusDays() > 0 &&
                    dto.getNoviceSurplusInvestMoney().compareTo(BigDecimal.ZERO) > 0) ? (byte) 1 : (byte) 0;
        } else {
            userIdentity = (byte) 1;
        }
        return investService.getInvestmentRateInfo(userId,userIdentity);
    }
}